Thursday, September 1, 2016

Working with Native Bitmap pixel buffers in Xamarin.Forms

I mentioned in my previous post that extracting pixel buffers from native Bitmap API’s can be quite tricky. In this post I would like to share the approach that I took for extracting native Bitmap pixel buffers into an collection of Xamarin.Forms.Colors objects so it can be used from a portable class library. I wrote and used a more complex version of the code mentioned in this post on my last project where I was working with image detection and color analysis for an app using Xamarin.Forms, in this project all my color analysis was done in a Portable Class Library using an abstraction over the native bitmap data.

BitmapData abstraction

In .NET you had access to an API called System.Drawing.Bitmap which encapsulates a low-level Windows API called Bitmap from GDI. The managed Bitmap class exposed a method called LockBits which in return gave you a BitmapData instance. BitmapData exposed information that allows you to manipulate the pixel buffer at a pointer level and is the fastest and recommended way to analyze and manipulate pixel information. I loved the BitmapData class but my portable class library implementation will not contain anything but a pixel buffer in ARGB and a Get/SetPixel(x,y, Color) method and a method for getting the average color of a certain area in the Bitmap to demonstrate what this can be used for

Here's the code

public class BitmapData
{
    public BitmapData(Size size, int[] pixelBuffer)
    {
        Size = size;
        PixelBuffer = pixelBuffer;
    }

    public int[] PixelBuffer { get; }

    public Size Size { get; }

    public Color GetPixel(Point point) => GetPixel(point.X, point.Y);

    public Color GetPixel(double x, double y) => Color.FromUint((uint)PixelBuffer[(int)x * (int)y]);

    public void SetPixel(Point point, Color color) => SetPixel((int)point.X, (int)point.Y, color);

    public void SetPixel(double x, double y, Color color) => PixelBuffer[(int)(x * y)] = (int)(color.A * byte.MaxValue) << 24 |
                                                                                        ((int)color.R * byte.MaxValue) << 16 |
                                                                                        ((int)color.G * byte.MaxValue) << 8 |
                                                                                        ((int)color.B * byte.MaxValue) << 0;

    public Color GetAverageColor(params Rectangle[] rectangles)
    {
        var colors = new List<Color>();
        foreach (var rectangle in rectangles)
            for (var y = rectangle.Y; y < rectangle.Y + rectangle.Height; y++)
                for (var x = (int)rectangle.X; x < (int)rectangle.X + (int)rectangle.Width; x++)
                    colors.Add(GetPixel(x, y));

        var red = (int)(colors.Average(c => c.R) * byte.MaxValue);
        var blue = (int)(colors.Average(c => c.G) * byte.MaxValue);
        var green = (int)(colors.Average(c => c.B) * byte.MaxValue);
        var alpha = (int)(colors.Average(c => c.A) * byte.MaxValue);
            
        return Color.FromRgba(red, blue, green, alpha);
    }
}

UIImage to BitmapData (iOS)

To get the pixel buffer from a UIImage instance we need to draw it to a new drawing surface by calling DrawImage on an CGBitmapContext instance. When we construct the drawing surface we specify the pixel format and provide a pointer or an array of bytes in which the data will be written to. We need to specify that the pixels will contain a byte for each component, 4 bytes per pixel, and that the byte order is 32-bit Big Endian. We can also specify whether we specify the alpha component is in the most or least significant bits of each pixel, but for this example I will put it in the end since when I was researching about this, most of the examples I found used the least significant bit to store the alpha component.

Here's the code

public BitmapData Convert(object nativeBitmap)
{
    var image = (UIImage)nativeBitmap;
    return new BitmapData(new Xamarin.Forms.Size(image.Size.Width, image.Size.Height), GetPixels(image));
}

private static int[] GetPixels(UIImage image)
{
    const int bytesPerPixel = 4;
    const int bitsPerComponent = 8;
    const CGBitmapFlags flags = CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.PremultipliedLast;

    var width = (int)image.CGImage.Width;
    var height = (int)image.CGImage.Height;
    var bytesPerRow = bytesPerPixel * width;
    var buffer = new byte[bytesPerRow * height];
    var pixels = new int[width * height];

    var handle = GCHandle.Alloc(buffer);
    try
    {
        using (var colorSpace = CGColorSpace.CreateGenericRgb())
        using (var context = new CGBitmapContext(buffer, width, height, bitsPerComponent, bytesPerRow, colorSpace, flags))
            context.DrawImage(new RectangleF(0, 0, width, height), image.CGImage);

        for (var y = 0; y < height; y++)
        {
            var offset = y * width;
            for (var x = 0; x < width; x++)
            {
                var idx = bytesPerPixel * (offset + x);
                var r = buffer[idx + 0];
                var g = buffer[idx + 1];
                var b = buffer[idx + 2];
                var a = buffer[idx + 3];
                pixels[x * y] = a << 24 | r << 16 | g << 8 | b << 0;
            }
        }
    }
    finally
    {
        handle.Free();
    }

    return pixels;
}

Bitmap to BitmapData (Android)

This is pretty easy to do in Android as the Bitmap class exposes the GetPixels method to get the pixel buffer and the pixel information is conveniently stored in ARGB

Here's the code

public BitmapData Convert(object nativeBitmap)
{
    var bitmap = (Bitmap)nativeBitmap;
    var info = bitmap.GetBitmapInfo();
    var pixels = new int[info.Width * info.Height];
    bitmap.GetPixels(pixels, 0, (int)info.Width, 0, 0, (int)info.Width, (int)info.Height);
    return new BitmapData(new Xamarin.Forms.Size(info.Width, info.Height), pixels);
}

WriteableBitmap to BitmapData (Universal Windows Platform)

To do this using the Universal Windows Platform is a bit similar to iOS but is less complex. The WriteableBitmap class exposes a PixelBuffer as an IBuffer in which you can call the extension method ToArray() on to get an array of integers. The interesting part about the WriteableBitmap PixelBuffer is that it doesn't really say anywhere in the documentation (at least not directly) that the component order is BGRA, I only figured this out by reading the sample code provided in the WriteableBitmap documentation where it says in a code comment that WriteableBitmap uses BGRA format.

Here's the code

public BitmapData Convert(object nativeBitmap)
{
    var imageSource = (WriteableBitmap)nativeBitmap;
    var pixelData = GetPixelDataFromImage(imageSource).ToArray();
    return new BitmapData(new Size(imageSource.PixelWidth, imageSource.PixelHeight), pixelData);
}

private static IEnumerable<int> GetPixelDataFromImage(WriteableBitmap imageSource)
{
    const int bytesPerPixel = 4;
    var pixelHeight = imageSource.PixelHeight;
    var pixelWidth = imageSource.PixelWidth;
    var buffer = imageSource.PixelBuffer.ToArray();
    var pixels = new int[buffer.Length];

    for (var y = 0; y < pixelHeight; y++)
    {
        var offset = y * pixelWidth;
        for (var x = 0; x < pixelWidth; x++)
        {
            var idx = bytesPerPixel * (offset + x);
            var b = buffer[idx + 0];
            var g = buffer[idx + 1];
            var r = buffer[idx + 2];
            var a = buffer[idx + 3];
            pixels[x * y] = a << 24 | r << 16 | g << 8 | b << 0;
        }
    }

    return pixels;
}

I remember struggling quite a bit when I was figuring out what I just shared and I hope that some one out there might be able to make some good use of it.

Wednesday, August 31, 2016

Over 2 years of Xamarin

I have held radio silence for over 2 years because I am having a blast doing nothing but Xamarin based development. During this time I have been fully involved in building music apps that I actually use in my everyday life. I struggled with the pains and gained a love/hate relationship with the development tools I use. I work primarily on a Mac since the products we build only target iOS and Android and I adore Xamarin Studio, it’s super fast and simple and it reminds me of the good old bad days of Visual Studio from over a decade ago where it was pretty much just a big text editor with a few fancy features. Xamarin Studio of course has its ups and downs and sometimes it just doesn’t want to cooperate. Every time a new “stable” version is out I needed to make sure that I only update during non-busy days as I risk losing all productivity if I install an update with breaking changes, or an update that is just simply broken. Some updates do break stuff! Some breaking changes are minor and easy to fix and some are rather complex to work around the problem. I remember once, our builds broke because the command line build tooling somehow got deprecated suggesting us to move from MDTool to XBuild, although the change sounds trivial it costed me a full day of work to update all our build scripts and double check every single build configuration that they work as they should in our build servers

On top of having a full time position doing Xamarin development for a Music Services company, I also do a few side project. For these projects I use Xamarin.Forms as it shows a lot of promise. The early versions were terrible but they eventually got much better. For simple UI requirements its absolutely perfect. With Xamarin.Forms you can create a cross platform UI that you only write once using either a flavor of XAML or in code (using C# in my case). In Xamarin.Forms you can either take advantage of the sharable UI tooling so you only have to write the UI code once and have it rendered natively on iOS, Android, and Windows Phone, or you can create custom renderers that allow you fully control using the API’s of the platforms you target to implement the control or the entire screen. When you end up implementing the entire app using custom renderers then Xamarin.Forms starts making less sense for what you’re trying to build, but for Line-of-Business apps its perfect. I can really see a big future in Xamarin.Forms

Knowing and understanding the platform is always better than relying on cross platform tools. I have mostly been working on multi-platform solutions throughout my career and the experience I gained has been a great advantage for me as I understand how a lot of things work and why API’s do what they do. A good example of such cross platform issues is working with Bitmaps. In a nutshell, a bitmap is an array of 32-bit integers containing the Red-Blue-Green-Alpha pixel information. If you do cross platform development and image processing you will need to ensure that the order of the pixel information bytes are uniform so that the algorithm you work with will work across all the targetted platforms. This might come as a surprise to some but pixel information is stored differently for every platform’s Bitmap API, for example, iOS uses Red-Blue-Green-Alpha, Android uses Alpha-Red-Blue-Green, and Windows uses Blue-Green-Red-Alpha. All these platforms have API’s that allow you retrieve the pixel buffer (the array of 32-bit integers) in a single call avoiding calling using slow API’s like GetPixel(x,y) hundreds or even thousands of times. Too make things even more fun the Xamarin.Forms.Color structure has a static helper method called FromUint(uint argb) but the documentation (at the current time of writing) describes the method as Returns a new Color with the requested RGBA value and the method parameter is described as A uint that represents the ARGB value of the color and the return value is described as An RGBA color. So that was a bit confusing! Eventually Xamarin will correct these small details or developers will just have to live with them

I just ended a side project and will probably not take on any new side projects for a while so I can spend more time learning new awesome stuff, or in some case understanding old awesome stuff. I have a few hobby projects that I have been intending to open source for a while so I’ll probably finish those up and finally publish them. I had some a bit success with some open source projects such as SQL Compact Query Analyzer (50k downloads), SQL Compact Code Generator (15k downloads), and ResW File Code Generator (4k downloads), all which had very constructive and positive reviews. I always enjoyed building developer tools and I hope to get more of that done in the nearest future

Friday, May 2, 2014

My future is Xamarin

I have been creating software for handheld devices for over a decade now. I’ve seen interesting things come and go and also witnessed a couple of failures. A great part of my mobile development career involved consulting and I had loads of fun working with some very smart people doing all sorts of interesting stuff. But for the past year or so I felt like I fell into a deep whole. Normally I would provide consulting services for up to 6 months then move on to something else, but my last project was not the case. It was retailer solution and was not really interesting, not at all challenging, and was mostly tedious, and to make it worse I was targeting a 10 year old platform and needed to support an even older one. I first went along with this because the company was going through a hard time and could really use some revenue, at that time we had just let go of 1/3 of our staff and I felt lucky that I got to keep my job. I did my job the best I could even and delivered what needed to be shipped. As the project progressed and the requirement changes got out of hand I found myself in an endless loop of fixing then breaking then fixing stuff. Sometimes in life you just have to suck it up and do your job since after all it pays the bills, keeps a roof over our heads, and puts food on the table. This project has taken all of my time and energy. It was the main reason I have not posted a single article for an entire year!

During this time I paid a lot of attention (more than usual) to what was going on in the mobile space and I have grown an interest in Xamarin. I’ve seen more and more people adapt Xamarin and after trying it in a few small projects I could really see why. This means a lot coming from me since I am a huge fan of native platform development. I’ve done Android projects before where I used Java + Eclipse and iOS projects where I used Objective-C + XCode. But after seeing and trying out Xamarin, thanks to my experience with Android and iOS, I found myself immediately being productive. I love the fact that I can just use the official Android or iOS documentation pages and be able to implement it directly using Xamarin.
So after months of considerations I have decided to take a break from consulting and take on a full time position for a company called 24/7 Entertainment where I will be doing Xamarin development. I have worked with the company in the past where I helped them with some Windows Phone and Store music apps. I know the team from past work experiences and I know that they are loads of fun to work with and are very passionate about what they do. They believe in their products and all share common goals. They follow modern software development practices and use the latest and the greatest development tools and hardware. This job is going be fun, challenging, and simply great! I hope to learn, contribute, and have a blast!

Sunday, May 5, 2013

Integrating with the Windows Phone 8 Lock Screen

A nice new feature in Windows Phone 8 is integration with the lock screen. As a developer, you can now display notification icons the same way the Outlook app displays New Mail notifications. You can also change the background image of the lock screen from your app. The information used for displaying notification is the exact same information that an app uses to display notifications on the app’s primary tile regardless if the app is pinned to the start screen or not

Notification Icon

To display an icon on the lock screen you must follow a small set of strict rules on how your image file should be. The image has to be a 38 x 38 PNG image that contains only white pixels and some levels of transparency. Yes, I know it’s a bit strict but it makes sense as the icon notifications are designed to be very discreet.

App Manifest

You need to define a few extensions to let the operating system allow your app to integrate with the lock screen. So here’s what we need to do, open the WMAppManifest.xml file using an XML editor, to do this right click on the WMAppManifest.xml file and select Open With, and use the XML (Text) Editor. First, we need to define the <DeviceLockImageURI> element in the primary token. The DeviceLockImageURI describes which image file to display in the lock screen as an icon. To define DeviceLockImageURI, insert the following element in the <PrimaryToken>
<DeviceLockImageURI IsRelative="true"
                    IsResource="false">Assets\YourLockImage.png</DeviceLockImageURI>
Then, insert the following lines after the between the <Tokens> and <ScreenResolutions> definitions
<Extensions>
  <Extension ExtensionName="LockScreen_Notification_IconCount"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
  <Extension ExtensionName="LockScreen_Notification_TextField"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
  <Extension ExtensionName="LockScreen_Background"
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}"
             TaskID="_default" />
</Extensions>

Lock screen settings

Before our app can display notifications we need to configure our Lock Screen settings to allow the type of notification that we are interested in displaying. Currently an app can display 3 types of notifications: background image; detailed status; and quick status. Detailed status is similar to the textual calendar notifications that are displayed using the Outlook Calendar app. Quick status is similar to the way the Outlook Mail app displays notifications, an icon and a count indicator.

To configure the device to display notifications from your app, go to the settings app and select Lock screen

settings

In the lock screen settings, choose the notification type that will display notifications from our app

image

For this example we’ll show a quick status notification

quick status on

Code

To update the background image of the lock screen we need use the LockScreen class of the UserProfile API. First we check if the user configured the app to be able to set the background of the lock screen, we can do this through LockScreenManager class. If the app isn’t allowed to change the lock screen background then we can open the lock screen settings page.

Lock screen background (C#)

if (await LockScreenManager.RequestAccessAsync() == LockScreenRequestResult.Granted)
{
    var uri = new Uri("ms-appx:///Assets/LockScreenImage.png", UriKind.Absolute);
    LockScreen.SetImageUri(uri);
}
else
{
    // Open the Settings -> Lock Screen settings
    await Launcher.LaunchUriAsync(new Uri("ms-settings-lock:"));
}


To display an icon notification just update the primary application tile with a notification. We can do this by using the ShellTile API

Display notification (C#)

var tile = ShellTile.ActiveTiles.First();
var data = new FlipTileData
                {
                    Count = 1,
                    Title = "Lock Screen Demo"
                };
tile.Update(data);


To clear the notification just update the primary application tile to its original state

Clear notification (C#)

var tile = ShellTile.ActiveTiles.First();
var data = new FlipTileData
                {
                    Count = 0,
                    Title = "Lock Screen Demo"
                };
tile.Update(data);


Pretty simple isn’t it?

Testing on the Emulator

To test on the Windows Phone emulator you can use the Simulation Dashboard which integrates directly into Visual Studio. To launch this, go to Tools –> Simulation Dashboard. You can use this tool to Lock and Unlock the emulator to test your apps lock screen integration

image

I hope you found this interesting. You can grab the source code here

Monday, April 15, 2013

Using the Windows Phone Custom Contact Store

In previous versions of Windows Phone, you could always query the contact store to retrieve contact or calendar items. During that time I always wondered why I couldn’t just create my own contacts that can be shared with other applications and accessed through the People Hub. I guess more people had this problem and in Windows Phone 8 this has been addressed. Windows Phone 8 introduced the custom contact store in which apps can create contacts that are accessible from the People Hub and from other apps. Items in the custom contact store may only be modified by app that created them

How to create contacts in Windows Phone 8

In this section I would like to demonstrate how to use the custom contact store API. In order to do so we’ll create a UI that accepts the display name, email address, and mobile phone number. To make it a bit more fancy, we’ll add a feature that accepts a photo which can be loaded either from the camera or the media library

So here’s the code…

XAML
<phone:PhoneApplicationPage x:Class="CustomContactStore.MainPage"
                           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                           xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
                           xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
                           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                           mc:Ignorable="d"
                           FontFamily="{StaticResource PhoneFontFamilyNormal}"
                           FontSize="{StaticResource PhoneFontSizeNormal}"
                           Foreground="{StaticResource PhoneForegroundBrush}"
                           SupportedOrientations="Portrait"
                           Orientation="Portrait"
                           shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="CUSTOM CONTACT STORE" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0" />
            <TextBlock Text="Sample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" />
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <TextBlock Text="Display Name" VerticalAlignment="Center" />
                    <TextBox Grid.Column="1" Name="displayName" />
                    <TextBlock Grid.Row="1" Text="Email" VerticalAlignment="Center" />
                    <TextBox Grid.Row="1" Grid.Column="1" Name="email" />
                    <TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Mobile" />
                    <TextBox Grid.Row="2" Grid.Column="1" Name="mobile" />
                </Grid>
                <Button Content="Attach New Photo" Click="AttachNewPhotoClicked" />
                <Button Content="Attach Existing Photo" Click="AttachExistingPhotoClicked" />
                <Button Content="Save Contact" Click="AddClicked" />
            </StackPanel>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

Code Behind (C#)
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Tasks;
using Windows.Phone.PersonalInformation;

namespace CustomContactStore
{
    public partial class MainPage
    {
        private Stream photo;

        public MainPage()
        {
            InitializeComponent();
        }

        private async void AddClicked(object sender, RoutedEventArgs e)
        {
            var store = await ContactStore.CreateOrOpenAsync();
            var contact = new StoredContact(store)
                              {
                                  DisplayName = displayName.Text
                              };

            var props = await contact.GetPropertiesAsync();
            props.Add(KnownContactProperties.Email, email.Text);
            props.Add(KnownContactProperties.MobileTelephone, mobile.Text);

            if (photo != null)
                await contact.SetDisplayPictureAsync(photo.AsInputStream());

            await contact.SaveAsync();

            if (photo != null)
                photo.Dispose();
        }

        private void AttachNewPhotoClicked(object sender, RoutedEventArgs e)
        {
            var task = new CameraCaptureTask();
            task.Completed += OnTaskOnCompleted;
            task.Show();
        }

        private void OnTaskOnCompleted(object o, PhotoResult result)
        {
            photo = result.ChosenPhoto;
        }

        private void AttachExistingPhotoClicked(object sender, RoutedEventArgs e)
        {
            var task = new PhotoChooserTask();
            task.Completed += OnTaskOnCompleted;
            task.Show();
        }
    }
}

To create a custom contact we need to use the ContactStore API, we create an instance of this using the helper method CreateOrOpenAsync(). Now that we have an instance of the contact store, we create an instance of a StoredContact and set the DisplayName property to the value of the display name entered in the UI. The StoredContact object is very limited but we can add KnownContactProperties such as Email and MobileTelephone. This is done by using the GetPropertiesAsync() method of the StoredContact instance. The photos can be attached using the CameraCaptureTask or the PhotoChooserTask. We attach the photos by calling the SetDisplayPictureAsync() method of the StoredContact instance. The API’s for the custom contact store are pretty straight forward and easy to use.

Manifest

The custom contact store requires the ID_CAP_CONTACTS capability, we should enable that in the WMAppManifest.xml file. In order to that, in the Visual Studio Solution Explorer, expand the project properties folder and double click the WMAppManifest.xml file. This will open the new UI editor for the manifest file. Go to the Capabilities tab and enable the ID_CAP_CONTACTS

id_cap_contacts

Once the manifest file has been updated the app should be able to launch.

The user interface looks like this:

Custom Contact Store

Once the contact is created it will be available in the People Hub

People Hub

When the contact is viewed from the People Hub the owner of the contact will be displayed on top

Custom Contact

I hope you found this useful. You can check out the source code using the link below

Friday, January 18, 2013

The missing ResWFileCodeGenerator custom tool for Visual Studio 2012

I've been doing quite a lot of Windows Store Apps on Windows 8 lately. Ever since I started I always seemed to miss the ResXFileCodeGenerator custom tool. This is because in WinRT when you want to load a localized string in code then you will have to do something like this:

var resources = new ResourceLoader();
var localizedString = resources.GetString("SomeResourceName");

This of course can easily lead to a lot of errors. In my case I got a little to eager while refactoring and forgot to notice that I was also changing hard coded strings. This broke the code quite a lot. Because of this frustration I decided to implement my own custom tool since Microsoft didn't provide one

The project is open source and is available at CodePlex. Here's a preview of the description which I took directly from my CodePlex project site.

Project Description
A Visual Studio 2012 Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.

Features
- C# code generator
- VB.NET code generator


Visual Studio 2012 Custom Tool (C#)


Visual Studio 2012 Custom Tool (VB)


Resource File Contents


C# Usage
private string test1, test2, test3;

private void LoadLocalizedStrings()
{
    test1 = App1.LocalizedResources.Resources.Test1;
    test2 = App1.LocalizedResources.Resources.Test2;
    test3 = App1.LocalizedResources.Resources.Test3;
}

Visual Basic Usage
Dim test1, test2, test3

Private Sub LoadLocalizedStrings()
    test1 = AppVb.LocalizedStrings.Resources.Test1
    test2 = AppVb.LocalizedStrings.Resources.Test2
    test3 = AppVb.LocalizedStrings.Resources.Test3
End Sub

Generated C# Code
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.18010
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------
// <auto-generatedInfo>
//  This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
//  ResW File Code Generator was written by Christian Resma Helle
//  and is under GNU General Public License version 2 (GPLv2)
// 
//  This code contains a helper class exposing property representations
//  of the string resources defined in the specified .ResW file
// 
//  Generated: 11/08/2012 22:41:22
// </auto-generatedInfo>
// --------------------------------------------------------------------------------------------------
namespace App1.LocalizedResources
{
    using Windows.ApplicationModel.Resources;
    
    
    public partial class Resources
    {
        
        private static ResourceLoader resourceLoader = new ResourceLoader();
        
        /// <summary>
        /// Localized resource similar to "Test 1 value"
        /// </summary>
        public static string Test1
        {
            get
            {
                return resourceLoader.GetString("Test1");
            }
        }
        
        /// <summary>
        /// Localized resource similar to "Test 2 value"
        /// </summary>
        public static string Test2
        {
            get
            {
                return resourceLoader.GetString("Test2");
            }
        }
        
        /// <summary>
        /// Localized resource similar to "Test 3 value"
        /// </summary>
        public static string Test3
        {
            get
            {
                return resourceLoader.GetString("Test3");
            }
        }
    }
}

Generated Visual Basic Code
'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'     Runtime Version:4.0.30319.18010
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------

Option Strict Off
Option Explicit On

Imports Windows.ApplicationModel.Resources

'--------------------------------------------------------------------------------------------------
'<auto-generatedInfo>
' This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
' ResW File Code Generator was written by Christian Resma Helle
' and is under GNU General Public License version 2 (GPLv2)
'
' This code contains a helper class exposing property representations
' of the string resources defined in the specified .ResW file
'
' Generated: 11/12/2012 21:30:52
'</auto-generatedInfo>
'--------------------------------------------------------------------------------------------------
Namespace AppVb.LocalizedStrings
    
    Partial Public Class Resources
        
        Private Shared resourceLoader As ResourceLoader = New ResourceLoader()
        
        '''<summary>
        '''Localized resource similar to "Test 1 value"
        '''</summary>
        Public Shared ReadOnly Property Test1() As String
            Get
                Return resourceLoader.GetString("Test1")
            End Get
        End Property
        
        '''<summary>
        '''Localized resource similar to "Test 2 value"
        '''</summary>
        Public Shared ReadOnly Property Test2() As String
            Get
                Return resourceLoader.GetString("Test2")
            End Get
        End Property
        
        '''<summary>
        '''Localized resource similar to "Test 3 value"
        '''</summary>
        Public Shared ReadOnly Property Test3() As String
            Get
                Return resourceLoader.GetString("Test3")
            End Get
        End Property
    End Class
End Namespace