Pages

Friday, 14 February 2014

Save WriteableBitmap as StorageFile in WinRT app

WriteableBitmap is quite useful when app requires image processing. It provides a BitmapSource, which can be written & manipulated. Ultimately that bitmap source is supplied to image control of Windows 8 app. Majorly WritableBitmap is more used with WriteableBitmapEx library, which is a collection of extension methods for the WriteableBitmap.

But we won't go for manipulating images using WriteableBitmap or WriteableBitmapEx, but we step forward to the next step, which is saving it as file i.e. StorageFile. It's obvious that end user will definitely wants to share or save the modified image or better say WriteableBitmap. So we will need to convert WriteableBitmap to StorageFile.

Before going to code directly, let me explain API used in that. For image encoding WinRT offers BitmapEncoder class. For image encoding we have to select BitmapEncoderGuid which is basically format of image viz JPEG, PNG, TIFF, etc. It's actually unique identifier for each bitmap encoder.

We will first export WriteableBitmap's pixel buffer into byte array. After that we will initialize the bitmap encoder with Guid & destination file stream. At last we will set the pixel data to bitmap encoder. Bitmap encoder's SetPixelData(...) gets various parameters to write the pixels in various ways. Check out the method metadata given below. At last we will have the file ready. Let's check out the code.

Metadata of method and enum.

// Summary:
//     Specifies the alpha mode of pixel data.
public enum BitmapAlphaMode
{
    // Summary:
    //     The alpha value has been premultiplied. Each color is first scaled by the
    //     alpha value. The alpha value itself is the same in both straight and premultiplied
    //     alpha. Typically, no color channel value is greater than the alpha channel
    //     value. If a color channel value in a premultiplied format is greater than
    //     the alpha channel, the standard source-over blending math results in an additive
    //     blend.
    Premultiplied = 0,
    //
    // Summary:
    //     The alpha value has not been premultiplied. The alpha channel indicates the
    //     transparency of the color.
    Straight = 1,
    //
    // Summary:
    //     The alpha value is ignored.
    Ignore = 2,
}


// Summary:
//     Specifies the pixel format of pixel data. Each enumeration value defines
//     a channel ordering, bit depth, and type.
public enum BitmapPixelFormat
{
    // Summary:
    //     The pixel format is unknown.
    Unknown = 0,
    //
    // Summary:
    //     The pixel format is R16B16G16A16 unsigned integer.
    Rgba16 = 12,
    //
    // Summary:
    //     The pixel format is R8G8B8A8 unsigned integer.
    Rgba8 = 30,
    //
    // Summary:
    //     The pixel format is B8G8R8A8 unsigned integer.
    Bgra8 = 87,
}

// Summary:
//     Sets the frame bitmap pixel data using the parameters specified in the arguments.
//
// Parameters:
//   pixelFormat:
//     The pixel format of the pixel data.
//
//   alphaMode:
//     The alpha mode of the pixel data.
//
//   width:
//     The width, in pixels, of the pixel data.
//
//   height:
//     The height, in pixels, of the pixel data.
//
//   dpiX:
//     The horizontal resolution, in dots per inch, of the pixel data.
//
//   dpiY:
//     The vertical resolution, in dots per inch, of the pixel data.
//
//   pixels:
//     The pixel data.
public void SetPixelData(BitmapPixelFormat pixelFormat, BitmapAlphaMode alphaMode, uint width, uint height, double dpiX, double dpiY, byte[] pixels);

The code to convert WriteableBitmap object to StorageFile in WinRT app

using System.Runtime.InteropServices.WindowsRuntime;

private async Task<StorageFile> WriteableBitmapToStorageFile(WriteableBitmap WB, FileFormat fileFormat)
{
    string FileName = "MyFile.";
    Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
    switch (fileFormat)
    {
        case FileFormat.Jpeg:
            FileName += "jpeg";
            BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
            break;

        case FileFormat.Png:
            FileName += "png";
            BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
            break;

        case FileFormat.Bmp:
            FileName += "bmp";
            BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
            break;

        case FileFormat.Tiff:
            FileName += "tiff";
            BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
            break;

        case FileFormat.Gif:
            FileName += "gif";
            BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
            break;
    }

    var file = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync(FileName, CreationCollisionOption.GenerateUniqueName);
    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, 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();
    }
    return file;
}

private enum FileFormat
{
    Jpeg,
    Png,
    Bmp,
    Tiff,
    Gif
}

Don't forget to add System.Runtime.InteropServices.WindowsRuntime namespace.

I hope this blog post would be helpful to you. I request you to share it as much as you can. If you need any help shout out me on Twitter & Facebook or comment below. I will catch you ASAP. Cheers!

Wednesday, 5 February 2014

Meet Satya Nadella - Third CEO of Microsoft

It's official that former vice president of Microsoft’s Cloud and Enterprise group Satya Nadella is elected as CEO of Microsoft, succeeding Steve Ballmar.

When Steve Ballmar announced his retirement as CEO of Microsoft, each MS developer was thinking who will be the next? The Nokia-Microsoft deal was referring Stephen Elop could be next CEO but secret is revealed.

Satya has great India connection. He was born in Hyderabad. He is alma mater of Manipal Institute of Technology. He joined Microsoft 22 years ago. #SatyaNadella becomes trending topic on Twitter within few minutes after press release regarding the next CEO. He has worked for many departments in Microsoft, like
  • President of the Server & Tools
  • Senior Vice President of Research and Development for the Online Services Division
  • Vice President of the Microsoft Business Division
  • Corporate Vice President of Microsoft Business Solutions and Search & Advertising Platform Group
  • Vice president of Microsoft’s Cloud and Enterprise group
Steve Ballmar is a more of marketing guy but Satya is more of "techie" guy. He has many challenges to crack. Biggest challenge is to increase market share of Windows 8.1, Windows Phone 8 and Surface tablets. We can now expect Windows Phone 8.1's keynote from himself. Windows Azure is being managed under him so we are seeing Azure has gain awesome momentum. So we are hoping such momentum in the consumer products also.


Don't forget to check out the dedicated CEO pageI wish best of luck to Satya Nadella.

Friday, 31 January 2014

Disable WebView scrolling in Windows Store Apps

WebView is a control which enables developers to host the HTML content. In WinRT framework WebView still lacks some features when we compare it to the WebBrowser of WPF. WebView class inherits from FrameworkElement class, but many properties of base class in not working in WebView.

Recently I was creating an app and I want to disable the horizontal & vertical scrolling of WebView. I tried below given code.

<WebView x:Name="webView" Source="http://myawesomewebsite.com"
    ScrollViewer.VerticalScrollBarVisibility="Disabled"
    ScrollViewer.VerticalScrollMode="Disabled"/>

But it didn't work. I was getting annoyed. I start binging & googling but didn't get any solution. WebView doesn't have its template also. Then I start analyzing the control in microscopic way. Finally I get to know that the scroll bars are due to HTML content, WebView itself doesn't have its own scroll bars. So I decided to go for JavaScript way. I applied some CSS properties in HTML content using JavaScript. It will display only that HTML content which is being displayed in current viewport or say display area. WebView provides InvokeScript method, which executes the specified script function from the currently loaded HTML, with specific arguments. When WebView's LoadCompleted event occurs, I am invoking that JavaScript which disables the scrolling. Check out whole code given below.

string DisableScrollingJs = @"function RemoveScrolling()
                              {
                                  var styleElement = document.createElement('style');
                                  var styleText = 'body, html { overflow: hidden; }'
                                  var headElements = document.getElementsByTagName('head');
                                  styleElement.type = 'text/css';
                                  if (headElements.length == 1)
                                  {
                                      headElements[0].appendChild(styleElement);
                                  }
                                  else if (document.head)
                                  {
                                      document.head.appendChild(styleElement);
                                  }
                                  if (styleElement.styleSheet)
                                  {
                                      styleElement.styleSheet.cssText = styleText;
                                  }
                              }";

void webView_LoadCompleted(object sender, NavigationEventArgs e)
{
    webView.InvokeScript("eval", new[] { DisableScrollingJs });
}

I hope this blog post will help you while developing WebView oriented app if you required such feature to implement.
Web Informer Button