Showing posts with label win81. Show all posts
Showing posts with label win81. Show all posts

Friday, April 4, 2014

Content for the Modern Camera and Imaging Apps Build 2014 Session

I had a chance to give a presentation at Microsoft's largest developer conference //build 2014 about the great new capturing APIs. The session Modern Camera and Imaging Apps was given together with Jeff Day who's the Windows Camera API lead PM.

The session was recorded and available at Channel 9.

The slides can also be viewed / downloaded here.
The source code of the demos is available here.

Friday, January 31, 2014

No Biggie - How to Query the Available Storage Size in WinRT

Tape drive photo by P. Hollenback
The Windows Runtime (WinRT) provides a nice file IO API called Windows.Storage. Part of it are atomic operations to create files and folders, etc. It also has a KnownFolders class with static references to different library folders like documents, videos, photos, plus RemovableDevices. Additionally does ApplicationData.Current provide references to the app's temporary, local and roaming folder.
Unfortunately there's no built-in way to check for the available free storage size / free disk space at those locations, although there are scenarios where that information can be essential, especially when dealing with removable devices. But no worries, the good old Win32 has it covered with the GetFreeDiskSpaceEx  function and it can be used with Windows 8 and Windows Phone 8. In order to use it from managed code it just has to be called through P/Invoke or wrapped in a WinRT component which I prefer nowadays, therefore this post provides a short WinRT C++/Cx snippet.

I assume you know how to create a custom C++/Cx WinRT component with Visual Studio, if not go back to my previous blog post which shows just that.


How it works

  1. Open the generated precompiled header file pch.h of your WinRT component's Visual Studio project and add an include for windows.h:
    // pch.h - Header for standard system include files.
    #pragma once
    
    #include <windows.h>

  2. Open the header file of your component and add the method declaration of GetAvailableBytes to your WinRT component which will internally use the GetFreeDiskSpaceEx, but only takes a path as string parameter and returns a WinRT uint64 (unsigned long) type with the available free space in bytes.
    namespace MyNativeStuff
    {
        public ref class MyStorageExtensions sealed
        {
        public:
            uint64 GetAvailableBytes(Platform::String^ path);
        };
    }

  3. Add the method implementation in the source file of the component (.cpp).
    The GetDiskFreeSpaceEx function takes a pointer to an ULARGE_INTEGER which is an union from ancient times when compilers didn't support 64 bit types. Our method then returns the filled unsigned long QuadPart of it.
    #include "pch.h"
    #include "MyNativeStuff.h"
    
    using namespace MyNativeStuff;
    using namespace Platform;
    
    uint64 MyStorageExtensions::GetAvailableBytes(Platform::String^ path)
    {
        ULARGE_INTEGER availableBytesToCaller;
        availableBytesToCaller.QuadPart = 0;
    
        GetDiskFreeSpaceEx(path->Data(), &availableBytesToCaller, NULL, NULL);
    
        return availableBytesToCaller.QuadPart;
    }

  4. You are now ready to use the component in your managed C# code.
    var myNativeComponent = new MyNativeStuff.MyStorageExtensions();
    
    // Create a folder in temp folder of the app and check the available free space
    var myTempFolder = await ApplicationData.Current.TemporaryFolder.CreateFolderAsync("test", CreationCollisionOption.OpenIfExists);
    var availableSpaceTempFolder = myNativeComponent.GetAvailableBytes(myTempFolder.Path);
    
    // Create a folder in videos lib and check the available free space
    var myVideoFolder = await KnownFolders.VideosLibrary.CreateFolderAsync("test", 
    CreationCollisionOption.OpenIfExists);
    var availableSpaceVideoLib = myNativeComponent.GetAvailableBytes(myVideoFolder.Path);

Note, the GetFreeDiskSpaceEx works with any directory path the calling code is allowed to access.

Friday, December 20, 2013

How to Encode and Save a WriteableBitmap with Windows WinRT


Windows WinRT 8.1 brought the support of the RenderTargetBitmap and the ability to render the visual tree of the UI into a bitmap. WriteableBitmapEx makes it even easier in the latest version and you might end up in a situation where you want to save a WriteableBitmap to a file or to a stream in general. For that the raw pixel array of the WriteableBitmap needs to be encoded into a common format like JPEG, PNG, etc.

Here's a code snippet how this can be achieved:






private static async Task SaveWriteableBitmapAsJpeg(WriteableBitmap bmp, string fileName)
{
   // Create file in Pictures library and write jpeg to it
   var outputFile = await KnownFolders.PicturesLibrary.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
   using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
   {
      await EncodeWriteableBitmap(bmp, writeStream, BitmapEncoder.JpegEncoderId);
   }
   return outputFile;
}

private static async Task EncodeWriteableBitmap(WriteableBitmap bmp, IRandomAccessStream writeStream, Guid encoderId)
{         
   // Copy buffer to pixels
   byte[] pixels;
   using (var stream = bmp.PixelBuffer.AsStream())
   {
      pixels = new byte[(uint) stream.Length];
      await stream.ReadAsync(pixels, 0, pixels.Length);
   }

   // Encode pixels into stream
   var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
   encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
      (uint) bmp.PixelWidth, (uint) bmp.PixelHeight,
      96, 96, pixels);
   await encoder.FlushAsync();
}

It's all  pretty straightforward actually: The SaveWriteableBitmapAsJpeg creates a file in the user's pictures library and passes the file's stream and an BitmapEncoder ID on to the EncodeWriteableBitmap method which is doing the actual work. EncodeWriteableBitmap first copies the WriteableBitmap pixel buffer into a byte array, then creates the BitmapEncoder based on the file's stream and the desired BitmapEncoder ID, then sets the pixels and flushes all into the stream.
The BitmapEncoder class supports a couple of BitmapEncoder IDs out of the box like JPEG, PNG and more.