Desarrollando con la cámara de Windows Phone

Desarrollando con la cámara de Windows Phone

Este artículo es una traducción del artículo original encontrado en: http://create.msdn.com/en-US/education/quickstarts/Developing_with_the_Windows_Phone_Camera.

 

Silverlight para Windows Phone incluye varias herramientas de fácil uso para la cámara y el uso de fotos.  Aquí vamos a mostrar cómo tomar y guardar fotos con la cámara de Windows Phone y seleccionar y mostrar fotos de la galería interna de Windows Phone.

 

Este artículo se divide en las siguientes secciones:

 

·         Creando una interfaz de usuario para la cámara y visualización de fotos

·         Tomando, seleccionando y visualizando imágenes

·         Guardando imágenes en la Biblioteca de Imágenes

 

Descarga el código fuente completo de este tutorial, hospedado en la galería de código de  Silverlight para Windows Phone.

 

Creando una interfaz de usuario para la cámara y visualización de fotos

Inicia Visual Studio y comienza un proyecto de tipo "Silverlight para Windows Phone".  A continuación, crea una interfaz de usuario (UI) que tiene los siguientes elementos:

·         Dos campos TextBlock - uno con un nombre significativo que mostrará los mensajes de estado y una etiqueta TextBlock que dice simplemente: "Desconecte el teléfono del software de Zune para ejecutar!".

·         Un Image con un nombre significativo que tendrá su fuente dinámicamente actualizada para reflejar la nueva imagen que fue tomada o elegida.

·         Tres botones con nombres significativos que se utilizarán para tomar una nueva foto, mostrar una foto existente, y guardar en el almacenamiento del teléfono la foto mostrada.  En este artículo, estos botones se llaman takePhotoButton, choosePhotoButton y savePhotoButton, respectivamente.

Una distribución propuesta de estos elementos se muestra a continuación:

clip_image002

XAML

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Button Content="Take Photo" Height="72" HorizontalAlignment="Left"

Margin="12,6,0,0" Name="button1" VerticalAlignment="Top"

idth="189" Click="button1_Click" />

<Image Height="308" HorizontalAlignment="Left" Margin="27,275,0,0"

Name="myImage" Stretch="Fill" VerticalAlignment="Top"

Width="406"/>

<Button Content="Choose Existing" Height="72" HorizontalAlignment="Left"

Margin="194,6,0,0" Name="button2" VerticalAlignment="Top"

Width="239" Click="button2_Click" />

<TextBlock Height="30" HorizontalAlignment="Left" Margin="27,162,0,0"

Name="textBlock1" Text="Disconnect phone from Zune software to run!"

VerticalAlignment="Top" Width="406" />

<Button Content="Save Current Photo to Library" Height="72"

HorizontalAlignment="Left" Margin="12,84,0,0" Name="savePhotoButton"

VerticalAlignment="Top" Width="419" IsEnabled="False"

Click="savePhotoButton_Click" />

<TextBlock Height="71" HorizontalAlignment="Left" Margin="29,197,0,0"

Name="statusText" Text="" VerticalAlignment="Top" Width="402"

Foreground="Red" TextWrapping="Wrap" />

</Grid>

 

Como último paso antes de la codificación, agrega una referencia a Microsoft.Xna.Framework. Vamos a usar el espacio de nombres Microsoft.Xna.Framework.Media en este ensamblado con el fin de guardar las imágenes en la biblioteca de medios del teléfono, y éste debe ser referenciado por tu proyecto antes que cualquiera de sus tipos, eventos o métodos sean utilizados en tu aplicación.

 

Para agregar Microsoft.Xna.Framework en tu aplicación:

·         En el Explorador de soluciones, haz derecho en el nodo References en tu proyecto y a continuación, selecciona Add Reference.

·         Selecciona Microsoft.Xna.Framework de la lista y a continuación haz clic en OK.

 

Tomando, Seleccionando y visualizando imágenes

En el Explorador de soluciones, abre el archivo MainPage.xaml.cs, y agrega las siguientes líneas de código en la parte superior de la página, dejando las referencias por defecto en su lugar.

C#

using Microsoft.Phone.Tasks; using System.Windows.Media.Imaging; using System.IO; using System.IO.IsolatedStorage; using Microsoft.Xna.Framework.Media;

 

Esto le da acceso a tu código a los espacios de nombres necesarios para abrir la aplicación de la cámara en el teléfono y tomar una imagen, usar un objeto de mapa de bits de re-escritura para almacenar los datos de la imagen temporal, usar un stream de memoria para convertir la imagen en un archivo, guardar la imagen en el almacenamiento interno del teléfono, y mover una imagen del almacenamiento aislado del teléfono a la biblioteca multimedia del teléfono, respectivamente.

 

La selección de fotos y el uso de la cámara requerirán la coordinación entre algunos métodos, así que vamos a añadir algunos miembros de datos a la clase principal.  Dos de ellos serán objetos Selectores, que permiten a las aplicaciones ceder el control a la funcionalidad integrada en el sistema operativo del teléfono a fin de facilitar las cosas como la elección de un contacto de una lista, tomar una foto, o seleccionar una foto de la galería de fotos del teléfono.  Otro será una imagen de mapa de bits que se estará utilizando para almacenar la información de la imagen temporal, es decir, imágenes que hemos elegido ya sea desde la galería en el teléfono o simplemente tomadas con la cámara.

C#

public partial class MainPage : PhoneApplicationPage

{

// Declarar el objeto CameraCaptureTask con ámbito de la página.

CameraCaptureTask cameraCaptureTask;

PhotoChooserTask photoChooserTask;

BitmapImage bmp;

 

cameraCaptureTask y photoChooserTask van a necesitar conectar los manejadores de eventos que se disparan cuando se toma una fotografía o cuando se elige de la  biblioteca de imágenes del teléfono, respectivamente.  Esto significa que los dos eventos deben ser manejados:

  1. Evento Completed de cameraCaptureTask.
  2. Evento Completed de photoChooserTask.

Este tutorial tiene una peculiaridad: porque en ambos casos sólo queremos mostrar la imagen en pantalla, y porque los eventos Completed envían el mismo tipo de objeto a sus manejadores (un PhotoResult), usaremos un método para manejar ambos eventos.  Vamos a llamar a este método photoCaptureOrSelectionCompleted, y obtendrá la foto que ha sido tomada por la cámara o seleccionada de la biblioteca de imágenes, y la mostrará en la pantalla.  La conexión de ambos eventos Completed para este nuevo método se realiza en la función de inicio de la página, MainPage, dando como resultado lo siguiente:

C#

 

public MainPage()

{

InitializeComponent();

// Inicializa los objetos Selectores y asigna los manejadores para los eventos "Completed"

cameraCaptureTask = new CameraCaptureTask();

cameraCaptureTask.Completed += new EventHandler<PhotoResult>(photoCaptureOrSelectionCompleted);

photoChooserTask = new PhotoChooserTask();

photoChooserTask.Completed += new EventHandler<PhotoResult<(photoCaptureOrSelectionCompleted);

}

 

Anteriormente, cuando creamos la interfaz de usuario, agregamos un Image llamado myImage en la pantalla, pero no estableció su propiedad Source, dejándola en blanco.  En photoCaptureOrSelectionCompleted, sabemos que el usuario ha tomado o seleccionado una imagen así que es momento de establecer la propiedad Source de myImage a esa imagen, después escalar la imagen de modo que quepa la zona de visualización de myImage.  También actualizaremos el TextBlock statusText si es necesario.  Por último, vamos a activar el botón que permite al usuario guardar la imagen mostrada.

 

La propiedad Stretch del objeto Image determina cómo la imagen será escalada para ajustarla a las dimensiones de myImage; utilizaremos Stretch.Uniform para preservar la relación de aspecto de la imagen original.

 

Así que podemos reservar la opción de guardar esta imagen si el usuario lo desea, utilizando el mapa de bits que hemos creado antes, llamado bmp, para recibir los datos de esta nueva imagen, entonces lo asignaremos a la propiedad Source de myImage de modo que se muestre en la pantalla.  (En otro método que implementaremos después, el contenido de bmp se puede guardar en el almacenamiento interno del teléfono). El aspecto final de photoCaptureOrSelectionCompleted será así:

C#

void photoCaptureOrSelectionCompleted(object sender, PhotoResult e)

{

if (e.TaskResult == TaskResult.OK)

{

bmp = new BitmapImage();

bmp.SetSource(e.ChosenPhoto);

myImage.Source = bmp;

myImage.Stretch = Stretch.Uniform;

// Intercambio los estados de los elementos en la IU

savePhotoButton.IsEnabled = true;

statusText.Text = "";

}

else

{

savePhotoButton.IsEnabled = false;

statusText.Text = "Task Result Error: " + e.TaskResult.ToString();

}

}

Ahora conectamos los botones que colocamos en la interfaz de usuario para iniciar un Selector que nos permitirá tomar o seleccionar una imagen.  Regresa al diseñador de la interfaz de usuario y haz doble clic en el botón "Take Photo".   Esto crea un manejador de evento que será disparado cuando se haga clic en el botón.  Nuestro botón se llama takePhotoButton, y sólo necesita una línea de código para iniciar el Selector.  El evento Completed se disparará cuando la foto sea tomada, manejando el resto.  El resultado es una función muy simple llamada takePhotoButton_Click:

C#

// La cámara muestra el Choosers en respuesta a un clic del botón.

private void takePhotoButton_Click(object sender, RoutedEventArgs e)

{

cameraCaptureTask.Show();

}

 

Ahora haz doble clic en el botón "Choose Existing", que nombramos choosePhotoButton.  Una vez más, es sólo una línea de código para iniciar el Selector que selecciona una foto, lo que resulta en un choosePhotoButton_Click que tiene este aspecto:

C#

// El selector de foto en respuesta a un clic del botón

 private void choosePhotoButton_Click(object sender, RoutedEventArgs e)

{

photoChooserTask.Show();

}

 

Ahora la aplicación es capaz de capturar y seleccionar imágenes existentes y mostrarlas en la pantalla en su relación de aspecto correcto.

Como la advertencia en la interfaz de usuario dice, el teléfono debe estar desconectado del software de Zune para que los Selectores sean lanzados correctamente.

 

Guardando imágenes en la Biblioteca de Imágenes

Con el fin de guardar la imagen a la biblioteca de imágenes del teléfono, debe ser primero codificada como un JPEG mediante la clase Extensions del espacio de nombres System.Windows.Media.Imaging.  Entonces, el ensamblado XNA que hemos importado se utilizará para usar la clase MediaLibrary, cuyo método SavePicture finalmente escribe la imagen a la biblioteca de imágenes del teléfono, donde puede ser sincronizada con la computadora, visualizada en una presentación, etc.

 

Debido a que este proceso implica ambos pasos: guardar la imagen como JPEG y luego importarla a la biblioteca, vamos a escribir un archivo JPEG temporal en el almacenamiento interno del teléfono, conocido como el Almacenamiento Aislado.  Entre otras cosas, el Almacenamiento Aislado para Windows Phone asigna un espacio exclusivo y seguro de archivos para cada aplicación en el teléfono.  No vamos a entrar en detalles aquí con el uso del Almacenamiento Aislado, sólo tenemos que utilizar el espacio de almacenamiento de nuestra aplicación para escribir nuestro archivo JPEG temporal.  Se trata de crear primero un archivo vacío, luego asignarle contenido.  El tipo WriteableBitmap será usado para esta tarea, recibiendo el contenido de bmp, nuestros datos de imagen que creamos con anterioridad.  Por último, queremos actualizar el Textblock statusText cuando tenemos un resultado al guardar la imagen.

 

Regresa al diseñador de la interfaz de usuario y haz doble clic en el botón "Save Current Photo to Library", al que llamamos savePhotoButton.  Al igual que con los otros botones, esto conecta un manejador de eventos en blanco al evento Click en el botón.  Una vez implementado para cubrir todas las funcionalidades descritas, la versión final de savePhotoButton_Click se verá así:

 

 

 

private void savePhotoButton_Click(object sender, RoutedEventArgs e)

{

try

{

// Crea un nombre de archivo para el archivo JPEG en el almacenamiento aislado.

String tempJPEG = "TempJPEG";

// Crea el almacenamiento virtual y el stream del archivo. Compruebe si hay archivos duplicados tempJPEG.

var myStore = IsolatedStorageFile.GetUserStoreForApplication();

if (myStore.FileExists(tempJPEG))

{

myStore.DeleteFile(tempJPEG);

}

IsolatedStorageFileStream myFileStream = myStore.CreateFile(tempJPEG);

/ / Se crea un stream del archivo JPEG.
/ / En lugar de MyQuickApp en la URI, utilice el nombre de proyecto correcto.
/ / El uso de TempJPEG se estableció anteriormente.

Uri uri = new Uri("MyQuickApp;component/TempJPEG.jpg", UriKind.Relative);

// Crear un nuevo objeto WriteableBitmap y establece el stream de JPEG.

WriteableBitmap wb = new WriteableBitmap(bmp);

/ / Codifica un objeto WriteableBitmap a un stream  JPEG.
/ / SaveJpeg (mapa de bits WriteableBitmap, targetStream Stream, targetWidth int,
/ / targetHeight int, int orientación, la calidad int)
Extensions.SaveJpeg(wb, myFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);

myFileStream.Close();

/ Se crea un nuevo stream en el almacenamiento aislado, y guarda el archivo JPEG
/ / en la biblioteca de medios de Windows Phone.

myFileStream = myStore.OpenFile(tempJPEG, FileMode.Open, FileAccess.Read);

MediaLibrary library = new MediaLibrary();

Picture pic = library.SavePicture("SavedPicture.jpg", myFileStream);

myFileStream.Close();

savePhotoButton.IsEnabled = false;

statusText.Text = "Saved!";

}

catch (Exception myError)

{

statusText.Text = myError.Message;

}

}

 

Este tutorial se ha completado, y ahora tienes un ejemplo de un programa que controla la entrada de la cámara, además de leer y escribir en la biblioteca de fotos.  Recuerda desconectar el teléfono del software Zune para que los Selectores en el método Start se puedan ejecutar.

7 thoughts on “Desarrollando con la cámara de Windows Phone

  1. jesus

    gracias por sus tutoriales de verdad una cosa maravillosa,
    mucho mas y gracias

  2. Andy

    Desearía hacer una consulta. Cuando una captura una instantanea con la cámara de Windows Phone el móvil como se comporta. Me explico, el móvil guarda automaticamente en el álbum o galería la instantanea o debe ser guardada manualmente por el programador, en todos los escenarios. Me refiero usando claro esta la clase CameraCaptureTask. Gracias.

  3. Gustavo Pages

    Excelente tutorial, de casualidad no tendrás como modificar una imagen cargada ponerle filtros y todo eso???
    me serviría mucho gracias

  4. Candyvf

    Necesito hacerte un par de consultas, me puedo poner en contacto con vos o directamente te las hago por aca?¿ Muy buen tutorial, muy útil. Gracias

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">