# Cómo cargar una imagen desde archivo o desde la red

> Cargar un PNG/JPEG/GIF desde un archivo local o descargado de la red y mostrarlo con ImageView.

Source: https://crossfly.dev/es/docs/cookbook/images/carregar-arquivo-rede — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Cómo cargar una imagen desde archivo o desde la red

**Propósito.** Cargar un archivo de imagen (PNG, JPEG o GIF) desde una ruta local o desde bytes
descargados de la red y mostrarlo en pantalla con un `ImageView`. Este es el camino más común para mostrar
fotos, íconos e ilustraciones.

## APIs usadas
- `new Image(String path) throws ImageException, IOException` — carga la imagen desde una ruta de archivo. Lanza `ImageException` si el archivo no se encuentra (cuando `width == 0` tras la lectura).
- `new Image(byte[] bytes) throws ImageException` — decodifica la imagen a partir de un array de bytes ya en memoria (PNG/JPEG/GIF). Usa este constructor para datos descargados de la red.
- `new ImageView(Image image, ImageSize imageSize)` — crea el widget que dibuja la imagen. Con `ImageSize.RATIO` la imagen se escala uniformemente preservando la proporción (letter-boxing), sin recortar.
- `ImageView.imageSize(ImageSize)` / `.alignX(Position)` / `.alignY(Position)` — setters fluidos para ajustar el modo de dimensionamiento y la alineación (por defecto `Position.CENTER`).

> Divergencia Javadoc×código: el Javadoc de `new Image(String)` dice "@throws ImageException When
> the file was not found", pero la firma real también declara `IOException`. Trata ambas.

## Ejemplo completo (copiar, pegar y ejecutar)

```java
package com.exemplo;

import java.io.IOException;

import dev.crossfly.Main;                    // runOnPaintThreadAndWait
import dev.crossfly.ui.*;                     // Window, Component, ImageView, UIConstants.ImageSize
import dev.crossfly.ui.layout.*;             // VerticalLayout, LAY_FILL
import dev.crossfly.ui.image.*;              // Image, ImageException

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   private ImageView imageView;

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 1) A partir de un archivo local
      try {
         Image img = new Image("/sdcard/foto.jpg");   // puede lanzar ImageException / IOException
         ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
         add(LAY_FILL, iv);
      } catch (ImageException | IOException e) {
         // archivo no encontrado o corrupto
      }

      // 2) De la red: descarga y decodifica fuera de la paint thread, luego actualiza el widget
      imageView = new ImageView(null, UIConstants.ImageSize.RATIO);
      add(LAY_FILL, imageView);

      new Thread(() -> {
         try {
            byte[] data = baixarBytes("https://exemplo.com/foto.png"); // tu HTTP client
            Image img = new Image(data);              // decodifica fuera de la paint thread
            Main.runOnPaintThreadAndWait(() -> imageView.image(img));
         } catch (Exception e) {
            // maneja error de red/decodificación
         }
      }).start();
   }

   /** Stub: sustituye por tu cliente HTTP. */
   private byte[] baixarBytes(String url) throws IOException
   {
      return new byte[0];
   }
}
```

> El fragmento de abajo muestra **solo el núcleo**. Para ejecutarlo, colócalo en el esqueleto `MainWindow` de arriba.

## Fragmento mínimo

```java
// verificado en la fuente: Image.java (líneas 403, 432) e ImageView.java (línea 72)
import dev.crossfly.ui.image.*;   // Image, ImageException
import dev.crossfly.ui.*;         // ImageView, UIConstants.ImageSize

// 1) A partir de un archivo local
try {
   Image img = new Image("/sdcard/foto.jpg");   // puede lanzar ImageException / IOException
   ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
   add(iv, /* posición/layout de tu container */);
} catch (ImageException | java.io.IOException e) {
   // archivo no encontrado o corrupto
}
```

### Desde la red (descarga los bytes fuera de la paint thread)

`new Image(...)` decodifica píxeles y es una operación pesada. **Nunca** descargues ni decodifiques en la paint
thread. Descarga los bytes en un Thread de trabajo, crea la `Image` ahí y solo entonces actualiza el widget.

```java
// verificado en la fuente: new Image(byte[]) — Image.java línea 432
new Thread(() -> {
   try {
      byte[] data = baixarBytes("https://exemplo.com/foto.png"); // tu HTTP client
      Image img = new Image(data);              // decodifica fuera de la paint thread
      // ahora agenda la actualización de la UI en la paint thread
      Main.runOnPaintThreadAndWait(() -> imageView.image(img));
   } catch (Exception e) {
      // maneja error de red/decodificación
   }
}).start();
```

## Profundiza
- [Trabajo en segundo plano](/docs/data-and-services/background-work) — cómo salir de la paint thread para descargar y decodificar.
- [Widget ImageView](/docs/ui/widgets/imageview) e [Imágenes](/docs/ui/images-and-graphics/images) — modos de `ImageSize` y alineación.
- Receta hermana: [imagem-de-fundo.md](/docs/cookbook/images/imagem-de-fundo).
