You are on page 1of 1

| Centro de desarrollo de Windows Aplicaciones de UWP Introducción Más  Panel 

Filtrar por título

Docs / Windows / UWP / Develop / Audio, video, and camera / Develop apps / +  Leer en inglés
Detect and respond to audio
Audio, video,
state and camera / Create, edit, and save bitmap images
changes Iniciar sesión
Create, edit, and save bitmap

7 Esteimages
artículo lo ha traducido una máquina. Puede mostrar el texto en inglés en una ventana emergente
Deshabilitar
moviendo el cursor
Process del mouse
bitmaps with sobre el texto.
OpenCV

Process bitmaps with the


LowLightFusion API

BitmapEncoder options
Crear, editar y guardar
reference
Image metadata
imágenes de mapa de bits
 21/03/2018  Tiempo de lectura: 14 minutos
Transcode media files
En este artículo
Process media files in the
background Crear un objeto SoftwareBitmap desde un archivo de imagen con BitmapDecoder

Audio graphs Guardar un elemento SoftwareBitmap en un archivo con BitmapEncoder

MIDI Usar SoftwareBitmap con un control de imagen XAML

Import media from a device Crear un objeto SoftwareBitmap desde un objeto WriteableBitmap
Crear o editar un objeto SoftwareBitmap mediante programación
C i d d Comentarios
Crear un objeto SoftwareBitmap desde una superficie de Direct3D
Convertir un objeto SoftwareBitmap a un formato de píxel diferente
Transcodificar un archivo de imagen
Temas relacionados

En este artículo se explica cómo cargar y guardar archivos de imagen mediante


BitmapDecoder y BitmapEncoder, y cómo usar el objeto SoftwareBitmap para
representar imágenes de mapa de bits.

La clase SoftwareBitmap es una API versátil que se puede crear desde varios
orígenes, entre los que se incluyen archivos de imagen, objetos WriteableBitmap,
superficies de Direct3D y código. SoftwareBitmap permite convertir fácilmente
entre los modos alfa y formatos de píxel diferentes, y también permite el acceso
de bajo nivel a datos de píxel. Además, SoftwareBitmap es una interfaz común
que utilizan varias características de Windows, entre las que se incluyen:

CapturedFrame permite obtener fotogramas capturados por la cámara como


un elemento SoftwareBitmap.

VideoFrame permite obtener una representación SoftwareBitmap de un


elemento VideoFrame.

FaceDetector permite detectar caras en un elemento SoftwareBitmap.

El código de ejemplo de este artículo usa las API de los siguientes espacios de
nombres.

C# = Copiar

using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.Graphics.Imaging;
using Windows.UI.Xaml.Media.Imaging;

Crear un objeto SoftwareBitmap desde un


archivo de imagen con BitmapDecoder
Para crear un elemento SoftwareBitmap desde un archivo, obtén una instancia de
StorageFile que contenga los datos de la imagen. En este ejemplo se usa un
elemento FileOpenPicker para permitir al usuario seleccionar un archivo de
imagen.

C# = Copiar

FileOpenPicker fileOpenPicker = new FileOpenPicker();


fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;

var inputFile = await fileOpenPicker.PickSingleFileAsync();

if (inputFile == null)
{
// The user cancelled the picking operation
return;
}

Llama al método OpenAsync del objeto StorageFile para obtener una secuencia
de acceso aleatorio que contenga los datos de la imagen. Llama al método
estático BitmapDecoder.CreateAsync para obtener una instancia de la clase
BitmapDecoder para el flujo especificado. Llama a GetSoftwareBitmapAsync para
obtener un objeto SoftwareBitmap que contenga la imagen.

C# = Copiar

SoftwareBitmap softwareBitmap;

using (IRandomAccessStream stream = await inputFile.OpenAsync(FileAccessMo


{
// Create the decoder from the stream
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);

// Get the SoftwareBitmap representation of the file


softwareBitmap = await decoder.GetSoftwareBitmapAsync();
}

Guardar un elemento SoftwareBitmap en un


archivo con BitmapEncoder
Para guardar un elemento SoftwareBitmap en un archivo, obtén una instancia de
StorageFile en la que se guardará la imagen. En este ejemplo se usa un elemento
FileSavePicker para permitir al usuario seleccionar un archivo de salida.

C# = Copiar

FileSavePicker fileSavePicker = new FileSavePicker();


fileSavePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileSavePicker.FileTypeChoices.Add("JPEG files", new List<string>() { ".jp
fileSavePicker.SuggestedFileName = "image";

var outputFile = await fileSavePicker.PickSaveFileAsync();

if (outputFile == null)
{
// The user cancelled the picking operation
return;
}

Llama al método OpenAsync del objeto StorageFile para obtener una secuencia
de acceso aleatorio en el que se escribirá la imagen. Llama al método estático
BitmapEncoder.CreateAsync para obtener una instancia de la clase
BitmapEncoder para el flujo especificado. El primer parámetro para CreateAsync
es un GUID que representa el códec que se debe usar para codificar la imagen. La
clase BitmapEncoder expone una propiedad que contiene el identificador de cada
códec compatible con el codificador, como por ejemplo JpegEncoderId.

Usa el método SetSoftwareBitmap para establecer la imagen que se va a codificar.


Puedes establecer los valores de la propiedad BitmapTransform para aplicar
transformaciones básicas a la imagen mientras se codifica. La propiedad
IsThumbnailGenerated determina si el codificador genera una miniatura. Ten en
cuenta que no todos los formatos de archivo admiten las miniaturas, por lo que si
usas esta característica, debes capturar el error de operación no compatible que se
produce si las miniaturas no se admiten.

Llama a FlushAsync para hacer que el codificador escriba los datos de la imagen
en el archivo especificado.

C# = Copiar

private async void SaveSoftwareBitmapToFile(SoftwareBitmap softwareBitmap,


{
using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAcc
{
// Create an encoder with the desired format
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEnco

// Set the software bitmap


encoder.SetSoftwareBitmap(softwareBitmap);

// Set additional encoding parameters, if needed


encoder.BitmapTransform.ScaledWidth = 320;
encoder.BitmapTransform.ScaledHeight = 240;
encoder.BitmapTransform.Rotation = Windows.Graphics.Imaging.Bitmap
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMod
encoder.IsThumbnailGenerated = true;

try
{
await encoder.FlushAsync();
}
catch (Exception err)
{
const int WINCODEC_ERR_UNSUPPORTEDOPERATION = unchecked((int)0
switch (err.HResult)
{
case WINCODEC_ERR_UNSUPPORTEDOPERATION:
// If the encoder does not support writing a thumbnail
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw;
}
}

if (encoder.IsThumbnailGenerated == false)
{
await encoder.FlushAsync();
}

}
}

Puedes especificar opciones de codificación adicionales al crear el elemento


BitmapEncoder mediante la creación de un nuevo objeto BitmapPropertySet y
rellenándolo con uno o varios objetos BitmapTypedValue que representen la
configuración del codificador. Para obtener una lista de opciones de codificador
admitidas, consulta el tema de referencia de opciones de BitmapEncoder.

C# = Copiar

var propertySet = new Windows.Graphics.Imaging.BitmapPropertySet();


var qualityValue = new Windows.Graphics.Imaging.BitmapTypedValue(
1.0, // Maximum quality
Windows.Foundation.PropertyType.Single
);

propertySet.Add("ImageQuality", qualityValue);

await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(
Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId,
stream,
propertySet
);

Usar SoftwareBitmap con un control de


imagen XAML
Para mostrar una imagen dentro de una página XAML con el control Image, define
primero un control Image en la página XAML.

XML = Copiar

<Image x:Name="imageControl"/>

Actualmente, el control Image solo admite imágenes que usan la codificación


BGRA8 y el canal alfa premultiplicado o ningún canal alfa. Antes de intentar
mostrar una imagen, asegúrate de que tiene el formato correcto y, si no es así, usa
el método estático Convert de SoftwareBitmap para convertir la imagen al
formato compatible.

Crea un nuevo objeto SoftwareBitmapSource. Establece el contenido del objeto


de origen mediante una llamada a SetBitmapAsync y pásale un elemento
SoftwareBitmap. Después puedes establecer la propiedad Source del control
Image al objeto SoftwareBitmapSource recién creado.

C# = Copiar

if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
{
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFor
}

var source = new SoftwareBitmapSource();


await source.SetBitmapAsync(softwareBitmap);

// Set the source of the Image control


imageControl.Source = source;

También puedes usar SoftwareBitmapSource para establecer un elemento


SoftwareBitmap como la propiedad ImageSource de una clase ImageBrush.

Crear un objeto SoftwareBitmap desde un


objeto WriteableBitmap
Puedes crear un objeto SoftwareBitmap desde un objeto WriteableBitmap
existente mediante una llamada a SoftwareBitmap.CreateCopyFromBuffer y
facilitando la propiedad PixelBuffer del objeto WriteableBitmap para establecer
los datos de píxel. El segundo argumento permite solicitar un formato de píxel
para el objeto WriteableBitmap recién creado. Puedes usar las propiedades
PixelWidth y PixelHeight del objeto WriteableBitmap para especificar las
dimensiones de la nueva imagen.

C# = Copiar

SoftwareBitmap outputBitmap = SoftwareBitmap.CreateCopyFromBuffer(


writeableBitmap.PixelBuffer,
BitmapPixelFormat.Bgra8,
writeableBitmap.PixelWidth,
writeableBitmap.PixelHeight
);

Crear o editar un objeto SoftwareBitmap


mediante programación
Hasta ahora, este tema ha explicado cómo se trabaja con archivos de imagen.
También puedes crear un nuevo objeto SoftwareBitmap mediante programación
en código y usar la misma técnica para acceder y modificar los datos de píxel de
SoftwareBitmap.

SoftwareBitmap usa la interoperabilidad COM para exponer el búfer sin procesar


que contiene los datos de píxel.

Para usar la interoperabilidad COM, debes incluir una referencia al espacio de


nombres System.Runtime.InteropServices del proyecto.

C# = Copiar

using System.Runtime.InteropServices;

Inicializa la interfaz COM IMemoryBufferByteAccess agregando el código


siguiente dentro del espacio de nombres.

C# = Copiar

[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}

Crea un nuevo objeto SoftwareBitmap con el formato de píxel y el tamaño que


deseas. O bien, usa un objeto SoftwareBitmap existente del que quieras editar los
datos de píxel. Llama a SoftwareBitmap.LockBuffer para obtener una instancia de
la clase BitmapBuffer que represente el búfer de datos de píxel. Convierte el
elemento BitmapBuffer a la interfaz COM IMemoryBufferByteAccess y luego
llama a IMemoryBufferByteAccess.GetBuffer para rellenar una matriz de bytes
con los datos. Usa el método BitmapBuffer.GetPlaneDescription para obtener un
objeto BitmapPlaneDescription que te ayudará a calcular el desplazamiento del
búfer de cada píxel.

C# = Copiar

softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, 100, 100, Bit

using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessM


{
using (var reference = buffer.CreateReference())
{
byte* dataInBytes;
uint capacity;
((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, ou

// Fill-in the BGRA plane


BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0
for (int i = 0; i < bufferLayout.Height; i++)
{
for (int j = 0; j < bufferLayout.Width; j++)
{

byte value = (byte)((float)j / bufferLayout.Width * 255);


dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride
dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride
}
}
}
}

Como este método tiene acceso el búfer sin procesar subyacente a los tipos de
Windows Runtime, se debe declarar con la palabra clave unsafe. También debes
configurar el proyecto en Microsoft Visual Studio para permitir la compilación del
código no seguro; para ello, abre la página Propiedades del proyecto, haz clic en
la página de propiedades de Compilación y selecciona la casilla Permitir código
no seguro.

Crear un objeto SoftwareBitmap desde una


superficie de Direct3D
Para crear un objeto SoftwareBitmap desde una superficie de Direct3D, debes
incluir el espacio de nombres Windows.Graphics.DirectX.Direct3D11 en el
proyecto.

C# = Copiar

using Windows.Graphics.DirectX.Direct3D11;

Llama a CreateCopyFromSurfaceAsync para crear un nuevo objeto


SoftwareBitmap desde la superficie. Como su nombre indica, el nuevo objeto
SoftwareBitmap tiene una copia independiente de los datos de imagen. Las
modificaciones al objeto SoftwareBitmap no tendrán ningún efecto en la
superficie de Direct3D.

C# = Copiar

private async void CreateSoftwareBitmapFromSurface(IDirect3DSurface surfac


{
softwareBitmap = await SoftwareBitmap.CreateCopyFromSurfaceAsync(surfa
}

Convertir un objeto SoftwareBitmap a un


formato de píxel diferente
La clase SoftwareBitmap proporciona el método estático Convert que permite
crear fácilmente un nuevo objeto SoftwareBitmap que use el modo alfa y el
formato de píxel que se especifique desde un objeto SoftwareBitmap existente.
Ten en cuenta que el mapa de bits recién creado tiene una copia de los datos de
imagen. Las modificaciones en el nuevo mapa de bits no afectarán al mapa de bits
de origen.

C# = Copiar

SoftwareBitmap bitmapBGRA8 = SoftwareBitmap.Convert(softwareBitmap, Bitmap

Transcodificar un archivo de imagen


Puedes transcodificar un archivo de imagen directamente desde un elemento
BitmapDecoder a un elemento BitmapEncoder. Crear un elemento
IRandomAccessStream desde el archivo que se va a transcodificar. Crea un nuevo
objeto BitmapDecoder desde el flujo de entrada. Crea un nuevo elemento
InMemoryRandomAccessStream para el codificador en el que se va a escribir y
llama a BitmapEncoder.CreateForTranscodingAsync pasándole el flujo en
memoria y el objeto descodificador. Las opciones de codificación no son
compatibles al realizar la operación de transcodificación; en su lugar deberías usar
CreateAsync. Las propiedades del archivo de imagen de entrada que no se
establecieron específicamente en el codificador se escribirán sin cambios en el
archivo de salida. Llama a FlushAsync para que el codificador codifique en el flujo
en memoria. Por último, busca la secuencia de archivos y la secuencia en memoria
al principio y llama a CopyAsync para escribir la secuencia en memoria en la
secuencia de archivos.

C# = Copiar

private async void TranscodeImageFile(StorageFile imageFile)


{

using (IRandomAccessStream fileStream = await imageFile.OpenAsync(File


{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream

var memStream = new Windows.Storage.Streams.InMemoryRandomAccessSt


BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAs

encoder.BitmapTransform.ScaledWidth = 320;
encoder.BitmapTransform.ScaledHeight = 240;

await encoder.FlushAsync();

memStream.Seek(0);
fileStream.Seek(0);
fileStream.Size = 0;
await RandomAccessStream.CopyAsync(memStream, fileStream);

memStream.Dispose();
}
}

Temas relacionados
Referencia de opciones de BitmapEncoder
Metadatos de imagen

 Español (España)

Documentación de versiones anteriores • Blog • Contribuir • Privacidad & cookies • Términos de uso • Comentarios del sitio •
Marcas comerciales

You might also like