> ## Documentation Index
> Fetch the complete documentation index at: https://docs.embededitor.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Obfuscate and Marks

> Hide parts of the photo and adjust the watermark and the signature from code, as the Obfuscate tool and the marks' items do.

`obfuscate` draws, changes and removes the areas that hide parts of the photo. `marks` adjusts the watermark and the signature you gave the editor. Each command does what the same gesture or control does on screen, with its undo step, and follows [the rules of every command](https://docs.embededitor.com/api-reference/commands/overview.md#how-every-command-behaves).

The examples call the handle `editor`. See [Get the handle](https://docs.embededitor.com/api-reference/commands/overview.md#get-the-handle).

> [!NOTE]
>
> Full and Trial only. In the Free and the Lite both groups exist and every command rejects with `NOT_AVAILABLE`.

Values are the ones [EditState](https://docs.embededitor.com/api-reference/state.md) writes: px of the size the editor works the photo at, degrees, strength 0 to 100, and the marks' sizes in % of the photo's shorter side.

## Obfuscate

```ts theme={"dark"}
obfuscate: {
	add: (input: {
		angle?: number;
		color?: string;
		height: number;
		shape?: 'ELLIPSE' | 'RECT' | 'ROUNDED';
		strength?: number;
		style?: 'BLUR' | 'PIXELATE' | 'SOLID';
		width: number;
		x: number;
		y: number;
	}) => Promise<{ index: number }>;
	remove: (input: { index: number }) => Promise<null>;
	select: (input: { index: number | null }) => Promise<null>;
	setLook: (input: { color?: string; shape?: 'ELLIPSE' | 'RECT' | 'ROUNDED'; strength?: number; style?: 'BLUR' | 'PIXELATE' | 'SOLID' }) => Promise<null>;
	update: (input: {
		angle?: number;
		color?: string;
		height?: number;
		index: number;
		shape?: 'ELLIPSE' | 'RECT' | 'ROUNDED';
		strength?: number;
		style?: 'BLUR' | 'PIXELATE' | 'SOLID';
		width?: number;
		x?: number;
		y?: number;
	}) => Promise<null>;
};
```

Obfuscate is off when you set `enableObfuscate: false`, and then every command here rejects with `NOT_AVAILABLE`.

An area has no id. Each command finds it by its `index` in the state's `obfuscation` list, the order it was drawn in. Removing an area moves the ones after it up one.

### add()

Draws a new area, as a drag on the photo does.

**x, y, width, height** `number` *required*

The area's rect, in px. As with a drag, a side under 1 px draws no area, and neither does a rect with nothing of it on the crop.

**style** `'BLUR' | 'PIXELATE' | 'SOLID'`

How it hides. Left out, the next area's: what Obfuscate's controls show with no area selected, `'BLUR'` until the user changes it.

**shape** `'RECT' | 'ROUNDED' | 'ELLIPSE'`

Square, rounded or round. Left out, the next area's.

**strength** `number`

0 to 100. Left out, the next area's (50 by default).

**color** `string`

A solid area's color, a hex. Left out, the next area's (black by default).

**angle** `number`

Its turn on the photo, in degrees. Left out, the area is born level on the screen, as a drawn one is, whatever the photo's turn.

It resolves to `{ index }`, the new area's place in `obfuscation`. While Obfuscate is open, the new area is selected, as a drawn one is. One undo step. With 64 areas already, it rejects with `NOT_AVAILABLE`, as a drag draws no 65th.

### setLook()

Sets the next area's look, as Obfuscate's controls do with no area selected. Give any of `style`, `shape`, `strength` (0 to 100) and `color` (a solid area's color, a hex). The rest stays. `add()` then draws in that look, unless its own input says otherwise.

It sets the next area's look even while an area is selected. That area keeps its own look; use `update()` to change it. The look is the editor's session state, so there is no undo step and it is never saved. An empty input changes nothing.

### update()

Changes what you give of the area at `index`: any of `x`, `y`, `width`, `height`, `angle`, `style`, `shape`, `strength` and `color`. The rest stays. One undo step, or none when nothing changes.

The area lands where its drags would hold it. It is turned, resized and moved as far as a handle's worth of it stays on the crop, so a rect asked past the crop's edge stops there. An area the crop left out goes no further off. While Obfuscate is open, the area is selected.

### remove()

Removes the area at `index`, as Delete removes the selected one. Nothing stays selected. One undo step.

### select()

Selects the area at `index`, as a tap on it: Obfuscate opens if it isn't open, and its controls show that area's look. `{ index: null }` lets the selection go. No undo step. While Annotate is open Obfuscate isn't on screen, so it rejects with `NOT_AVAILABLE`: call `annotate.close()` first.

```ts obfuscate.ts theme={"dark"}
const { index } = await editor.obfuscate.add({ height: 90, style: 'PIXELATE', width: 160, x: 120, y: 80 });

await editor.obfuscate.update({ color: '#1f2937', index, style: 'SOLID' });
await editor.obfuscate.select({ index });
await editor.obfuscate.remove({ index });
```

```ts look.ts theme={"dark"}
await editor.obfuscate.setLook({ shape: 'ELLIPSE', style: 'PIXELATE' });
await editor.obfuscate.add({ height: 90, width: 160, x: 120, y: 80 });
```

## Marks

```ts theme={"dark"}
marks: {
	hide: (input: { role: 'SIGNATURE' | 'WATERMARK' }) => Promise<null>;
	place: (input: {
		position?: 'BOTTOM' | 'BOTTOM_LEFT' | 'BOTTOM_RIGHT' | 'CENTER' | 'LEFT' | 'RIGHT' | 'TOP' | 'TOP_LEFT' | 'TOP_RIGHT';
		role: 'SIGNATURE';
		x?: number;
		y?: number;
	}) => Promise<null>;
	show: (input: { role: 'SIGNATURE' | 'WATERMARK' }) => Promise<null>;
	update: (input: {
		angle?: number;
		color?: 'AUTO' | string;
		font?: AnnotationFont;
		layout?: 'GRID' | 'SINGLE';
		margin?: number;
		opacity?: number;
		role: 'SIGNATURE' | 'WATERMARK';
		size?: number;
		spacing?: number;
		text?: string;
	}) => Promise<null>;
};
```

`role` names the mark. The commands adjust the marks you gave in the `watermark` and `signature` props, as far as their `lock` lets the user: a `'fixed'` mark takes none of them. What a command sets is what the state's `marks` keeps, and saving writes it there.

### update()

Changes a mark as its pill does: what you give changes, the rest stays, all of it one undo step. Each field below says which mark takes it. `color`, `font`, `opacity`, `size` and `text` belong to both.

**layout** `'GRID' | 'SINGLE'`

The watermark's layout. It is set first, so the values given in the same call land in this layout.

**size** `number`

The mark's height, in % of the photo's shorter side: 1 to 20 for a grid watermark, 4 to 60 for a single one, 2 to 40 for the signature.

**spacing** `number`

The grid's gap, 0 to 100. A grid watermark only.

**angle** `number`

The watermark's turn, −90 to 90 degrees.

**margin** `number`

The signature's distance to the edges, 0 to 20.

**opacity** `number`

10 to 100.

**color** `string`

`'AUTO'` (white or black, as the photo under the mark reads) or a hex. A logo signature keeps its own colors.

**font** `AnnotationFont`

A text mark's letter, by its slug.

**text** `string`

A free text mark's words, 1 to 80 characters, as its field's Done writes them: trimmed, and the host's text back when they are the host's. The field itself never opens.

### hide() and show()

Take a `'free'` mark out of the photo and the file, and bring it back, as its pill's Show does. One undo step each, none when the mark is already so.

### place()

Puts the signature at one of its 9 points (`position`: `'TOP_LEFT'`, `'TOP'`, `'TOP_RIGHT'`, `'LEFT'`, `'CENTER'`, `'RIGHT'`, `'BOTTOM_LEFT'`, `'BOTTOM'`, `'BOTTOM_RIGHT'`), or with its center at a spot of the final photo (`x` and `y`, 0 to 1). Give one of the two. A spot lands as a drag drops the signature: within 6% of the photo's shorter side of a point, it sticks to that point, and the signature always stays whole on the photo. One undo step.

```ts marks.ts theme={"dark"}
// with watermark={{ lock: 'free', text: '© Lume' }} and signature={{ text: '© Ana Prado' }}
await editor.marks.update({ layout: 'SINGLE', opacity: 50, role: 'WATERMARK', text: 'Draft' });
await editor.marks.place({ position: 'TOP_LEFT', role: 'SIGNATURE' });
await editor.marks.hide({ role: 'SIGNATURE' });
await editor.marks.show({ role: 'SIGNATURE' });
```

## Errors

| `code` | When |
| - | - |
| `NOT_AVAILABLE` | Obfuscate is off, `obfuscate.add` finds 64 areas already, or `obfuscate.select` is called while Annotate is open. The mark isn't there or is `'fixed'`, or its props forbid what you set: a logo's `font` and `text`, a logo signature's `color`, a `'required'` mark's `text` and hiding. Also always in the Free and the Lite. |
| `NOT_FOUND` | No area at `index`. |
| `INVALID_COMMAND` | An input off its schema, `props` naming each path (`input.strength`). Also an area a drag never draws (a side under 1 px, nothing of it on the crop), a field of the other mark (`margin` on the watermark; `angle`, `layout` or `spacing` on the signature), a `size` off its range, and a `spacing` on a single watermark. |

A rejected command changes nothing.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.