ImageBitmap vs. ImageVector

Los dos tipos más frecuentes de formatos de imagen son las imágenes de trama y las vectoriales.

Un formato gráfico de trama contiene píxeles: pequeños cuadrados individuales que contienen un color (compuesto por rojo, verde, azul y valores alfa). Cuando se colocan muchos píxeles juntos, se puede formar una imagen muy detallada, como una fotografía. Un gráfico de trama tiene una resolución fija (número fijo de píxeles). Es decir, cuando aumentas el tamaño de la imagen, pierdes detalles y esta se puede pixelar. Algunos ejemplos de formatos gráficos de trama son JPEG, PNG y WEBP.

Ejemplo de archivo JPEG
Figura 1: Ejemplo de archivo JPEG

Por otro lado, las imágenes vectoriales son representaciones matemáticas escalables de un elemento visual en pantalla. Un vector es un conjunto de comandos que describen cómo dibujar la imagen en la pantalla, por ejemplo, una línea, un punto o un relleno. Cuando se escala un vector en la pantalla, no perderá calidad, ya que la fórmula matemática mantendrá la relación entre los diferentes comandos. Un buen ejemplo de ImageVector son los símbolos de Material, ya que todos pueden definirse con fórmulas matemáticas.

Ejemplo de imagen vectorial (las extensiones de archivo son .xml o se definen en código Kotlin)
Figura 2: Ejemplo de imagen vectorial (las extensiones de archivo son .xml o se definen en código Kotlin)

ImageBitmap

En Compose, una imagen de trama (con frecuencia, denominada Bitmap) se puede cargar en una instancia de ImageBitmap, y un elemento BitmapPainter es el que se encarga de dibujar el mapa de bits en pantalla.

Para casos de uso simples, se puede usar painterResource(), que se encarga de crear un ImageBitmap y muestra un objeto Painter (en este caso, un BitmapPainter):

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description)
)

Si necesitas mayor personalización (por ejemplo, una implementación de pintor personalizada) y necesitas acceso al mismo objeto ImageBitmap, puedes cargarlo de la siguiente manera:

val imageBitmap = ImageBitmap.imageResource(R.drawable.dog)

ImageVector

Un VectorPainter se encarga de dibujar un ImageVector en pantalla. ImageVector admite un subconjunto de comandos SVG. No todas las imágenes pueden representarse como vectores (por ejemplo, las fotos que tomas con tu cámara no se pueden transformar en un vector).

Puedes crear un ImageVector personalizado importando un archivo en formato XML de un elemento de diseño vectorial existente (importado a Android Studio con la herramienta de importación) o implementando la clase y emitiendo comandos de ruta de acceso de forma manual.

En casos de uso simples, de la misma manera en que painterResource() funciona para la clase ImageBitmap, también funciona para ImageVectors y muestra un VectorPainter como resultado. painterResource() controla la carga de VectorDrawables y BitmapDrawables en VectorPainter y BitmapPainter, respectivamente. Para cargar un VectorDrawable en una imagen, usa lo siguiente:

Image(
    painter = painterResource(id = R.drawable.baseline_shopping_cart_24),
    contentDescription = stringResource(id = R.string.shopping_cart_content_desc)
)

Si requieres mayor personalización y necesitas acceder al mismo objeto ImageVector, puedes cargarlo de la siguiente manera:

val imageVector = ImageVector.vectorResource(id = R.drawable.baseline_shopping_cart_24)