Saving an Image to the Pictures Hub

Something that will also be discussed during the upcoming Windows Phone course, here at U2U, is the cooperation between Silverlight for Windows Phone and XNA.

At the end of my previous blog post, I was left with one more challenge: saving my modified picture to the Pictures Hub. Until shortly I thought that the only way of using the Pictures Hub was through the PhotoChooserTask or the CameraCaptureTask. Luckily I came across the MediaLibrary-class from the XNA-framework, who gives much more possibilities for accessing your pictures.

To start I needed to add a reference to Microsoft.Xna.Framework. This results in an alarming message :

image

At first I tried to do some experimenting with the MediaLibrary. Let’s start by simply getting the number of pictures I have on the emulator :

ml = new MediaLibrary();
nrOfPics = ml.Pictures.Count;
MessageBox.Show(nrOfPics.ToString());

 

That works nice. The Medialibrary has several collection I can use, like Pictures, Songs, Genres,…

Next step : lets create a little slideshow-app for iterating through my pictures. I start out with a simple page :

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="523*" />
        <RowDefinition Height="84*" />
    </Grid.RowDefinitions>
    <Image Name="image1" Stretch="Fill" />
    <Grid Grid.Row="1" Name="grid1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Content="&gt;&gt;" Grid.Column="1" Name="btnGoForward" 
                Click="btnGoForward_Click" />
        <Button Content="&lt;&lt;" Name="btnGoBack" Click="btnGoBack_Click" />
    </Grid>
</Grid>

 

The code looks like this :

 1: public partial class MainPage : PhoneApplicationPage
 2: {
 3:     int nrOfPics;
 4:     int picNr = 0;
 5:     MediaLibrary ml;
 6:     BitmapImage img = new BitmapImage();
 7:  
 8:     // Constructor
 9:     public MainPage()
 10:     {
 11:         InitializeComponent();
 12:     }
 13:  
 14:     private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
 15:     {
 16:         ml = new MediaLibrary();
 17:         nrOfPics = ml.Pictures.Count;
 18:         MessageBox.Show(nrOfPics.ToString());
 19:         
 20:         ShowImage();
 21:     }
 22:  
 23:     private void ShowImage()
 24:     {
 25:         img.SetSource(ml.Pictures[picNr].GetImage());
 26:         image1.Source = img;
 27:     }
 28:  
 29:     private void btnGoBack_Click(object sender, RoutedEventArgs e)
 30:     {
 31:         if (--picNr<0)
 32:         {
 33:             picNr = nrOfPics - 1;
 34:         }
 35:         ShowImage();
 36:     }
 37:  
 38:     private void btnGoForward_Click(object sender, RoutedEventArgs e)
 39:     {
 40:         if (++picNr>=nrOfPics)
 41:         {
 42:             picNr = 0;
 43:         }
 44:         ShowImage();
 45:     }
 46: }

 

image

Let's now return to the application created during my previous blog post. In the "Save Img" code we opened another page that simply showed the image with copyright-message. Let's now change the loaded-event of the WrittenImage-page so we can save the image :

WriteableBitmap bmp = PhoneApplicationService.Current.State["bmp"] as WriteableBitmap;
writtenImage.Source = bmp;
 
MediaLibrary ml = new MediaLibrary();
Stream stream = new MemoryStream();
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
 
ml.SavePicture("u2uPic.jpg", stream);
 
MessageBox.Show("Picture Saved...");

 

The SaveJpeg-method from WritableBitmap gives me a Stream containing the image in jpg-format. SavePicture saves the image in the MediaLibrary. However: it doesn't work ! It took me some time to find out why: It seems that the position of the stream remains at the end-position. Insert this line of code just before the SavePicture-call to make it work:

stream.Position=0;
 

It's working !! Cool.

Next step: let's deploy these two apps to my device and test. Not working ! How the hell is that possible ? Retesting in the emulator : works fine. Retesting on device: not working. Aaaaargh !! Disconnecting my device, going over to a colleague to ventilate my frustration and see that all of a sudden it is working !! Seems that for this thing to work, it needs to be disconnected from the PC.

 

 

Adding a text to an image in WP7

Some time ago, somebody asked me if it was possible to add some text to an image, and then use the combination image-text as a new image. It seems that it’s rather easy to do, and it’s very similar to the way you could achieve this in regular Silverlight.

I started out by adding this piece of XAML to my MainPage :

<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>
<Grid.RowDefinitions>

<RowDefinition Height=”532*” />

<RowDefinition Height=”75*” />

</Grid.RowDefinitions>

<Grid Name=”TheImage”>

<Image Name=”sourceImg” Stretch=”Uniform”

Source=”/WritableBitMap;component/Images/BasilicaNotreDame_ROW459961203.jpg” />

<TextBlock VerticalAlignment=”Center” Text=”(c) U2U” HorizontalAlignment=”Center”/>

</Grid>
<Grid Grid.Row=”1″ Name=”grid1″>
<Grid.ColumnDefinitions>

<ColumnDefinition Width=”*” />

<ColumnDefinition Width=”*” />

</Grid.ColumnDefinitions>

<Button Content=”Get Picture” Name=”button1″ Click=”button1_Click” />

<Button Content=”Save Img” Grid.Column=”1″ Name=”addMsgButton”

Click=”addMsgButton_Click” />

</Grid>

</Grid>

This creates something like this :

What I need to do now, is to use the grid, combining the Image and the TextBlock, as a new Image. To make it a bit more complete I also added a Button for fetching a picture from the PictureHub:

private void button1_Click(object sender, RoutedEventArgs e)

{
PhotoChooserTask task = new PhotoChooserTask();

task.Completed += (s, ea) =>

{

img = new BitmapImage();

img.SetSource(ea.ChosenPhoto);

sourceImg.Source = img;

};

task.Show();

}
For creating an new Image, out of the original one plus the added TextBlock, I use the WriteableBitmap-class, which has a constructor that takes a UIElement as input. This one I save in the service-state, and I open another page (WrittenImage.xaml).

WriteableBitmap wbm = new WriteableBitmap(TheImage, null);

PhoneApplicationService.Current.State["bmp"] = wbm;

NavigationService.Navigate(new Uri(“/WrittenImage.xaml”, UriKind.Relative));

WrittenImage.xaml is a simple Page that only has one Image-control (called writtenImage, to make a little bit confusing – I like confusion, sometimes). In the loaded-event I have following code :

if (PhoneApplicationService.Current.State.ContainsKey(“bmp”))

{

writtenImage.Source = PhoneApplicationService.Current.State["bmp"] as WriteableBitmap;

}

Nice. The next question is then if it’s possible to save this image in the Picture-hub. That’s for a next time…

If you know of a more elegant way of adding text to an image, let it know !