# 获取屏幕像素 (Get Screen Pixels)

- **Summary**: `five.getPixels` 方法用于获取 Five 画布指定区域的像素数据（RGBA），常用于实现放大镜、取色器或截图功能。
- **Schema**: `GetPixelsOptions`。
- **Concepts**: `WebGLRenderTarget`, `gl.readPixels`, `Magnifier`。
- **Examples**: 放大镜实现、获取中心点颜色。

## Schema

> **Definition**: [GetPixelsOptions](../../five/application/five.d.ts)

`five.getPixels` 支持两种调用方式：参数列表（旧版）和对象参数（推荐）。

### 推荐调用方式

```typescript
five.getPixels(options: GetPixelsOptions): Uint8Array | Uint8ClampedArray;

interface GetPixelsOptions {
  /** 获取像素区域的起始坐标 x (基于 Canvas 左下角，除非 flipY 为 true) */
  x: number;
  /** 获取像素区域的起始坐标 y */
  y: number;
  /** 获取像素区域的宽度 */
  width: number;
  /** 获取像素区域的高度 */
  height: number;
  /** 获取区域的像素比 (默认 1) */
  pixelRatio?: number;
  /** 是否显示辅助元素 (默认 false) */
  helperVisible?: boolean;
  /** 是否跳过全景图渲染 (仅渲染模型) */
  skipPanorama?: boolean;
  /** 是否 Y 轴翻转 (通常设为 true 以匹配 Canvas 2D 坐标系) */
  flipY?: boolean;
  /** 存储数组 (可选，复用数组以提升性能) */
  buffer?: Uint8Array | Uint8ClampedArray;
}
```

### 简写调用方式 (不推荐)

```typescript
five.getPixels(
  x: number,
  y: number,
  width: number,
  height: number,
  pixelRatio?: number,
  flipY?: boolean,
  buffer?: Uint8Array | Uint8ClampedArray
): Uint8Array | Uint8ClampedArray;
```

## Concepts

### 坐标系统 (Coordinate System)

- **WebGL 坐标系**: 原点在左下角。
- **Canvas 2D 坐标系**: 原点在左上角。
- **flipY 参数**: 当你需要将数据绘制到 Canvas 2D Context (`putImageData`) 时，通常需要将 `flipY` 设置为 `true`，否则图像是倒置的。

### 性能注意事项 (Performance)

- `five.getPixels` 会触发 WebGL 的 `readPixels` 操作，这是一个同步且耗时的操作（会阻塞 GPU 流水线）。
- **优化建议**:
    - 避免在每一帧都调用。
    - 尽量复用 `buffer` 数组，避免频繁创建新的 `Uint8Array`。
    - 仅获取需要的区域（`width` 和 `height` 越小越好）。

## Examples

### 放大镜 (Magnifier)

这是一个经典的放大镜实现示例。通过获取鼠标周围的像素，并以更高的 `pixelRatio` 重新渲染，从而获得清晰的放大效果。

```typescript
import * as THREE from 'three';
import { Five } from '@realsee/five';

// 假设有一个用于显示的 canvas
const magnifierCanvas = document.getElementById('magnifier-canvas') as HTMLCanvasElement;
const ctx = magnifierCanvas.getContext('2d')!;
const magnifierSize = 200; // 放大镜尺寸 200px
const scale = 2; // 放大倍数

// 预先创建 Buffer 以提升性能
const pixelWidth = magnifierSize * scale;
const pixelHeight = magnifierSize * scale;
let magnifierImageData = ctx.createImageData(pixelWidth, pixelHeight);

five.on('gesture.mousemove', (event) => {
  // 1. 获取鼠标在 Canvas 上的坐标
  const mouse = event.pointers[0]?.coords;
  if (!mouse) return;

  // 转换归一化坐标 (-1 到 1) 到 像素坐标
  const renderSize = five.getSize(new THREE.Vector2());
  const x = (mouse.x + 1) / 2 * renderSize.x;
  const y = (mouse.y + 1) / 2 * renderSize.y;

  // 2. 获取像素数据
  // 注意：我们以更高的分辨率 (pixelRatio * scale) 渲染小区域，从而获得“无损”放大效果
  const pixelRatio = five.renderer?.getPixelRatio() ?? 1;
  const targetPixelRatio = Math.ceil(pixelRatio * scale);

  five.getPixels({
    x: x - magnifierSize / 2, // 居中
    y: y - magnifierSize / 2,
    width: magnifierSize,
    height: magnifierSize,
    pixelRatio: targetPixelRatio,
    flipY: true, // 翻转以适配 Canvas 2D
    buffer: magnifierImageData.data, // 复用 buffer
    helperVisible: false, // 隐藏辅助线等干扰元素
  });

  // 3. 将数据绘制到放大镜 Canvas 上
  // 需要调整 Canvas 尺寸以匹配数据
  magnifierCanvas.width = pixelWidth;
  magnifierCanvas.height = pixelHeight;
  ctx.putImageData(magnifierImageData, 0, 0);

  // 4. 更新放大镜位置 (CSS)
  magnifierCanvas.style.left = `${x - magnifierSize / 2}px`;
  magnifierCanvas.style.top = `${renderSize.y - y - magnifierSize / 2}px`; // 注意 Y 轴方向
});
```

### 获取中心点颜色 (Color Picker)

获取屏幕中心点的颜色。

```typescript
function getCenterColor(five: Five) {
  const size = five.getSize(new THREE.Vector2());
  const x = size.x / 2;
  const y = size.y / 2;

  const pixels = five.getPixels({
    x: x,
    y: y,
    width: 1,
    height: 1,
    flipY: true
  });

  const r = pixels[0];
  const g = pixels[1];
  const b = pixels[2];
  const a = pixels[3];

  return `rgba(${r}, ${g}, ${b}, ${a / 255})`;
}
```

## Common Pitfalls

1.  **坑点1: 图像倒置**:
    - **现象**: 获取到的图像是上下颠倒的。
    - **解决**: 检查 `flipY` 参数。如果直接用于 Canvas 2D `putImageData`，通常需要 `flipY: true`。

2.  **坑点2: 性能卡顿**:
    - **现象**: 开启放大镜后，页面帧率显著下降。
    - **解决**:
        - 确保使用了 `buffer` 参数复用内存。
        - 检查 `width` 和 `height` 是否过大。
        - 确保 `pixelRatio` 不要设置得过高（例如不要超过 4）。

3.  **坑点3: 渲染内容不全**:
    - **现象**: 放大镜里只有背景，没有模型。
    - **解决**: 检查 `skipPanorama` 参数。如果需要看全景图，确保设为 `false`（默认）。如果只想看模型细节（如在 Floorplan 模式），可以设为 `true`。

## Related

*   [API Reference](../api.md): Five 核心 API 说明。

---

```yaml
tags: [截图, 放大镜, 取色器, 颜色拾取, 像素数据, getPixels, magnifier, screenshot, pixel, canvas, screen-capture, color-picker]
```
