Showing posts with label Store apps. Show all posts
Showing posts with label Store apps. Show all posts

Wednesday, September 23, 2015

We've Come a Long Way Baby - WriteableBitmapEx now on GitHub


The WriteableBitmapEx project is now 6 years old and times have changed since all began. It all started with Silverlight and more XAML flavors were added over time until all XAML flavors were supported including Windows Phone, WPF, WinRT Windows Store XAML, (Windows 10) UWP and still Silverlight.

The version control system and open source services landscape has changed as well and the CodePlex infrastructure has not been too reliable recently. That's why I finally took the time to move the WriteableBitmapEx source code from CodePlex' SVN bridge to Git and make it available on GitHubhttps://github.com/teichgraf/WriteableBitmapEx
Additionally was the open source license changed from Ms-PL to MIT which should simplify the usage as well. See the Codeplex Issue Tracker for a list of features that will be added in the future. Please use the GitHub Issues functionality to add new issues which are not already reported. Of course the latest binaries will continue to be distributed via NuGet.

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.

Thursday, November 1, 2012

WACK ARM

If you are developing Windows 8 Store apps you should really test those on low-powered x86 and ARM devices. The difference to your high-end x64 developer machine can be dramatically, esp. if you use a non-default design.
Testing on ARM is important and Tim Heuer wrote a nice post which shows how to remotely deploy, debug and profile on ARM devices right from Visual Studio 2012. Another nice thing which performs a couple of automated tests is the Windows App Certification Kit (WACK). Unfortunately is the WACK tool for ARM hidden inside the Windows 8 SDK, but here's how to find it:

  1. Download the Windows 8 SDK web setup from here and run it.
  2. Choose to download the SDK files for offline usage.
  3. On the "Select the features you want to download" screen it's enough if you only select the "Windows App Certification Kit" checkbox.
  4. After the download is finished, you will find an "Installers" subfolder in the download target folder.
  5. Copy the "Windows App Certification Kit arm-arm_en-us.msi" from the "Installers" folder to an USB key or SkyDrive.
  6. Open the "Windows App Certification Kit arm-arm_en-us.msi" on your ARM device and install the WACK on it. 
  7. Search for "Windows App Cert Kit" on your ARM device using the Search Charm and run the WACK.

Sunday, October 28, 2012

Know Your Users - Windows 8 Store App System Info

This is just a quick a post to provide a little class for Windows 8 Store app development. The SystemInformation class gathers some useful information about the current system and can dump those as a string. I usually have such a class for all the platforms I work on and it's very helpful for logging and error analysis, but it also serves as a list of all available system information which are scattered in different APIs. The info can also be used to dynamically adapt the app, etc.

Here's the code I have so far, you can also download the complete class here.

public static async Task Dump(bool shouldDumpCompleteDeviceInfos = false)
{
   var builder = new StringBuilder();
   var packageId = Windows.ApplicationModel.Package.Current.Id;
   var clientDeviceInformation = new EasClientDeviceInformation();
    
   // Get hardware Id
   var token = HardwareIdentification.GetPackageSpecificToken(null);
   var stream = token.Id.AsStream();
   string hardwareId;
   using (var reader = new BinaryReader(stream))
   {
      var bytes = reader.ReadBytes((int)stream.Length);
      hardwareId = BitConverter.ToString(bytes);
   }

   builder.AppendLine("***** System Infos *****");
   builder.AppendLine();
#if DEBUG
   builder.AppendLine("DEBUG");
   builder.AppendLine();
#endif
   builder.AppendFormat("Time: {0}", DateTime.Now.ToUniversalTime().ToString("r"));
   builder.AppendLine();
   builder.AppendFormat("App Name: {0}", packageId.Name);
   builder.AppendLine();
   builder.AppendFormat("App Version: {0}.{1}.{2}.{3}", packageId.Version.Major, packageId.Version.Minor, packageId.Version.Build, packageId.Version.Revision);
   builder.AppendLine();
   builder.AppendFormat("App Publisher: {0}", packageId.Publisher);
   builder.AppendLine();
   builder.AppendFormat("Supported Package Architecture: {0}", packageId.Architecture);
   builder.AppendLine();
   builder.AppendFormat("Installed Location: {0}", Windows.ApplicationModel.Package.Current.InstalledLocation.Path);
   builder.AppendLine();
   builder.AppendFormat("Store App Id: {0}", CurrentApp.AppId);
   builder.AppendLine();
   if (CurrentApp.LicenseInformation.IsActive)
   {
      var listingInformation = await CurrentApp.LoadListingInformationAsync();
      builder.AppendFormat("Store Current Market: {0}", listingInformation.CurrentMarket);
      builder.AppendLine();
   }
   builder.AppendFormat("Culture: {0}", CultureInfo.CurrentCulture);
   builder.AppendLine();
   builder.AppendFormat("OS: {0}", clientDeviceInformation.OperatingSystem);
   builder.AppendLine(); 
   builder.AppendFormat("System Manufacturer: {0}", clientDeviceInformation.SystemManufacturer);
   builder.AppendLine();
   builder.AppendFormat("System Product Name: {0}", clientDeviceInformation.SystemProductName);
   builder.AppendLine();
   builder.AppendFormat("System Sku: {0}", clientDeviceInformation.SystemSku);
   builder.AppendLine();
   builder.AppendFormat("System Name: {0}", clientDeviceInformation.FriendlyName);
   builder.AppendLine();
   builder.AppendFormat("System ID: {0}", clientDeviceInformation.Id);
   builder.AppendLine();
   builder.AppendFormat("Hardware ID: {0}", hardwareId);
   builder.AppendLine();
   builder.AppendFormat("User Display Name: {0}", await UserInformation.GetDisplayNameAsync());
   builder.AppendLine();
   builder.AppendFormat("Window Bounds w x h: {0} x {1}", Window.Current.Bounds.Width, Window.Current.Bounds.Height);
   builder.AppendLine();
   builder.AppendFormat("Current Orientation: {0}", DisplayProperties.CurrentOrientation);
   builder.AppendLine();
   builder.AppendFormat("Native Orientation: {0}", DisplayProperties.NativeOrientation);
   builder.AppendLine();
   builder.AppendFormat("Logical DPI: {0}", DisplayProperties.LogicalDpi);
   builder.AppendLine();
   builder.AppendFormat("Resolution Scale: {0}", DisplayProperties.ResolutionScale);
   builder.AppendLine();
   builder.AppendFormat("Is Stereo Enabled: {0}", DisplayProperties.StereoEnabled);
   builder.AppendLine();
   builder.AppendFormat("Supports Keyboard: {0}", IsKeyboardPresent());
   builder.AppendLine();
   builder.AppendFormat("Supports Mouse: {0}", IsMousePresent());
   builder.AppendLine();
   builder.AppendFormat("Supports Touch (contacts): {0} ({1})", IsTouchPresent(), new TouchCapabilities().Contacts);
   builder.AppendLine();
   builder.AppendFormat("Is Network Available: {0}", NetworkInterface.GetIsNetworkAvailable());
   builder.AppendLine();
   builder.AppendFormat("Is Internet Connection Available: {0}", NetworkInformation.GetInternetConnectionProfile() != null);
   builder.AppendLine();
   builder.AppendFormat("Network Host Names: ");
   foreach (var hostName in NetworkInformation.GetHostNames())
   {
      builder.AppendFormat("{0} ({1}), ", hostName.DisplayName, hostName.Type);
   }
   builder.AppendLine();
   builder.AppendFormat("Current Memory Usage: {0:f3} MB", GC.GetTotalMemory(false) / 1024f / 1024f);
   builder.AppendLine();
   builder.AppendFormat("App Temp  Folder: {0}", ApplicationData.Current.TemporaryFolder.Path);
   builder.AppendLine();
   builder.AppendFormat("App Local Folder: {0}", ApplicationData.Current.LocalFolder.Path);
   builder.AppendLine();
   builder.AppendFormat("App Roam  Folder: {0}", ApplicationData.Current.RoamingFolder.Path);
   builder.AppendLine();
   builder.AppendLine();

   if (shouldDumpCompleteDeviceInfos)
   {
      var devInfos = await DeviceInformation.FindAllAsync();
      builder.AppendLine();
      builder.AppendLine("Complete Device Infos:");
      foreach (var devInfo in devInfos)
      {
         builder.AppendFormat("Name: {0} Id: {1} - Properties: ", devInfo.Name, devInfo.Id);
         foreach (var pair in devInfo.Properties)
         {
            builder.AppendFormat("{0} = {1}, ", pair.Key, pair.Value);
         }
         builder.AppendLine();
      }
   }

   return builder.ToString();
}

public static bool IsTouchPresent()
{
 return new TouchCapabilities().TouchPresent == 1;
}

public static bool IsMousePresent()
{
 return new MouseCapabilities().MousePresent == 1;
}

public static bool IsKeyboardPresent()
{
 return new KeyboardCapabilities().KeyboardPresent == 1;
}


On my system it provides the following info (anonymized):
***** System Infos *****

DEBUG

Time: Sun, 28 Oct 2012 07:51:11 GMT
App Name: MyApp
App Version: 1.0.0.5
App Publisher: CN=A8E2F0B1-4749-48AE-AE18-C7FFB5B30272
Supported Package Architecture: Neutral
Installed Location: D:\Development\MyApp\bin\Debug\AppX
Store App Id: 00000000-0000-0000-0000-000000000000
Culture: en-US
OS: WINDOWS
System Manufacturer: Dell Inc.
System Product Name: Precision M6600
System Sku: 
System Name: MYLAPTOP
System ID: 18a2e8c6-cc7d-8546-1e9e-56a12ffb32fd
Hardware ID: 03-00-D2-41-03-00-AA-72-08-00-EF-AD-05-AA-B6-4F-06-00-01-01-04-00-31-1B-04-00-0C-48-04-00-D2-55-04-00-D3-66-01-00-0E-D6-02-00-E4-7F-09-00-56-47
User Display Name: Rene Schulte
Window Bounds w x h: 1920 x 1080
Current Orientation: Landscape
Native Orientation: Landscape
Logical DPI: 96
Resolution Scale: Scale100Percent
Is Stereo Enabled: False
Supports Keyboard: True
Supports Mouse: True
Supports Touch (contacts): False (0)
Is Network Available: True
Is Internet Connection Available: True
Network Host Names: mylaptop (DomainName), mylaptop.local (DomainName), 169.254.85.85 (Ipv4), 192.168.2.148 (Ipv4), 
Current Memory Usage: 0.451 MB
App Temp  Folder: C:\Users\Rene\AppData\Local\Packages\MyApp\TempState
App Local Folder: C:\Users\Rene\AppData\Local\Packages\MyApp\LocalState
App Roam  Folder: C:\Users\Rene\AppData\Local\Packages\MyApp\RoamingState

If you know more system information Windows 8 APIs that listing is missing, please add a comment.