# 图像

> 使用 ImageView 加载和显示图像，缩放模式（ImageSize）以及背景图像。

Source: https://crossfly.dev/zh/docs/ui/images-and-graphics/images — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 图像（`ImageView`）

`ImageView` 在组件内显示一个 `Image`，可控制**缩放**（`ImageSize`）和**对齐**。

## 完整示例（复制、粘贴并运行）
```java
package com.exemplo;

import java.io.*;                     // IOException

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.image.*;       // Image, ImageException
import dev.crossfly.util.*;           // Debug

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 带回退加载：new Image(path) 会抛出 ImageException/IOException（受检异常）。
      Image logo;
      try
      {
         logo = new Image("images/logo.png");   // 应用的资源路径
      }
      catch (ImageException | IOException e)
      {
         Debug.log("falha ao carregar: " + e);
         return;   // 若图片缺失则中止装配
      }

      // 用 ImageView 显示，保持比例（RATIO）并居中。
      ImageView foto = new ImageView(logo, ImageSize.RATIO)
         .alignX(Position.CENTER)
         .alignY(Position.CENTER);
      add(0.4f, foto);   // 高度的 40%（VerticalLayout）

      // 窗口自身的背景图（Component 的方法，而非 ImageView）。
      addBackgroundImage(logo, ImageSize.FIT, 0.5f, 0.5f);   // 居中，覆盖
   }
}
```
> 下面的片段只展示了**核心部分**（放入 `onShow()` 内部的内容）。要运行它们，请将其放入上面的 `MainWindow` 骨架中。

## 加载一个 `Image`
```java
Image logo;
try {
   logo = new Image("images/logo.png");   // 应用的资源路径
} catch (ImageException | IOException e) {
   Debug.log("falha ao carregar: " + e);
   return;
}
```
常用构造函数：`new Image(String path)`、`new Image(byte[] bytes)`、`new Image(InputStream)`、
`new Image(int w, int h)`（用于绘制的空位图）。**它们都可能抛出 `ImageException`**（其中
path/stream 的还会抛出 `IOException`）。

## 显示
```java
ImageView foto = new ImageView(logo, ImageSize.RATIO)
   .alignX(Position.CENTER)
   .alignY(Position.CENTER);
painel.add(0.4f, foto);   // 高度的 40%（VerticalLayout）
```
构造函数：`ImageView()`、`ImageView(Image)`、`ImageView(Image, ImageSize)`。流式：`.image(Image)`、
`.imageSize(ImageSize)`、`.alignX(Position)`、`.alignY(Position)`。

## 缩放模式（`ImageSize`）
| 模式 | 行为 |
|---|---|
| `ORIGINAL` | 以像素为单位的原始尺寸 |
| `RATIO` | 在保持比例的前提下**容纳于**组件内（可能留有空白） |
| `FIT` | 在保持比例的前提下**覆盖**组件（可能**裁剪**） |
| `STRETCH` | 拉伸以填充，**忽略**比例 |
| `FIT_WIDTH` / `FIT_HEIGHT` | 按宽度 / 高度调整，保持比例 |
| `FIT_HALF_WIDTH` / `FIT_HALF_HEIGHT` | 宽度 / 高度的一半 |

> 实用规则：**`RATIO`** = "完整显示"（letterbox）；**`FIT`** = "无失真填充"
> （裁掉多余部分）；**`STRETCH`** = 失真填充（照片中请避免使用）。

## 背景图像（组件/界面的）
它不是 `ImageView` — 而是 `Component` 自身的一个方法：
```java
janela.addBackgroundImage(fundo, ImageSize.FIT, 0.5f, 0.5f);   // 居中，覆盖
// 或通过 Relative 缩放：
janela.addBackgroundImage(marca, Relative.ofScreen(0.3f), null, 0.5f, 0.9f);
```
`centerX`/`centerY` 是 0–1（图像中心的相对位置）。

## 最佳实践
- 加载时**始终处理 `ImageException`/`IOException`** — 它们是受检异常。
- 照片：`RATIO`（显示全部）或 `FIT`（填充并裁剪）。避免 `STRETCH`（会失真）。
- 在 paint 线程之外加载大图，并通过 `Component.onUI(...)` 返回。

## 常见错误
- 不捕获 `new Image(...)` 的异常 → 无法编译。
- 在人物照片上使用 `STRETCH`（失真）；请用 `FIT`。
- 混淆 `RATIO`（容纳于内部）与 `FIT`（覆盖并裁剪）。

## 另请参阅
- [自定义绘制](/docs/ui/images-and-graphics/custom-drawing) · [Whiteboard](/docs/ui/images-and-graphics/whiteboard)
- 目录：[ImageView](/docs/ui/widgets/imageview) · 参考：第 18 章 — 图像
