> For the complete documentation index, see [llms.txt](https://ccfivem.gitbook.io/ccfivem-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ccfivem.gitbook.io/ccfivem-docs/free-resources/image-studio-tool-cc_images.md).

# Image Studio (tool) (cc\_images)

**Free tool · Standalone · Version 1.0.0**

cc\_images is a tool that lets your server create its **own** item and clothing images in game and serve them to other CrankChaos scripts from one central place — so every player downloads the image pool once, not once per script.

{% hint style="warning" %}
cc\_images ships **without any images**. It is a tool: the images are created on your own server by an admin.
{% endhint %}

## Features

* **Photo studio** (`/ccfoto`) for admins: photographs items (props) and clothing in game, removes the background automatically and saves transparent WebP images
* Difference keying (two shots in front of green and magenta) — works with objects of any colour and handles semi-transparent edges; classic chroma key available as an alternative
* Isolated studio: own routing bucket per admin, no traffic, no other players, fixed weather and time, HUD hidden, everything restored afterwards
* **Clothing batches**: all components, props and head overlays (beards, make-up, …) for both freemode models, resumable after an abort, with remaining-time estimate
* **Clothing catalogue** (`clothing/index.json`) with names, tags and measured colour groups — powers name search and colour filter in the clothing shop of cc\_character/00%20Overview\.md)
* Batch capture of missing weapon, ammo, attachment and food/drink item images from cc\_inventory/00%20Overview\.md)
* Live camera editor per body zone, saved as presets without restart
* **Portrait export** (`TakePortrait`) — passport photo for ID cards, licences, MDT and EMS tablet
* Item images visible **without restart** (kept in memory and sent by cc\_inventory)
* Secure uploads: ACE check on every upload, WebP-only, size limits, server-chosen file names, atomic writes, rate limiting

If cc\_images is not running or an image is missing, all interfaces show an icon of the same size — nothing breaks.

## Pages

* Installation
* Configuration
* API
* FAQ

Related: cc\_lib/00%20Overview\.md) · cc\_jobs/00%20Overview\.md) · Support

## Installation

### Dependencies

| Requirement                   | Required?                         | Purpose                                                  |
| ----------------------------- | --------------------------------- | -------------------------------------------------------- |
| Current FXServer with Node 22 | required                          | `node_version '22'` — writes image files                 |
| `screenshot-basic`            | required for studio and portraits | captures the game image; serving images works without it |

No SQL and no framework are needed.

### server.cfg

Start cc\_images **before** the scripts that display its images (e.g. cc\_inventory, cc\_character, cc\_licenses, cc\_police, cc\_ambulance):

```cfg
ensure screenshot-basic
ensure cc_images

## Who may use the photo studio
add_ace group.admin cc_images.foto allow

## Lets /ccfoto neustart and the batches restart cc_images itself
add_ace resource.cc_images command.restart allow
```

{% hint style="info" %}
The ACE name `cc_images.foto` is configurable via `Config.Foto.ace`. Without the `command.restart` ACE, the restart command tells you exactly that instead of silently doing nothing.
{% endhint %}

### First test

1. Add the ACEs above, restart the server, log in as admin.
2. Leave any vehicle (the studio does not work inside one).
3. Run `/ccfoto item water prop_ld_flow_bottle`.
4. A panel with progress and preview appears top-left. The screen flashes green and magenta — that is the colour wall.
5. The chat confirms the save; the file is in `cc_images/items/water.webp`.

### Framework-specific steps

None — cc\_images is standalone.

See also: General installation · Dependencies

## Configuration

Main file: `config/foto.lua`. Texts: `locales/en.json`, `locales/de.json`.

```lua
Config.Debug = false
Config.Locale = 'de'   -- set 'en' for English messages
```

### Photo studio (`Config.Foto`)

#### Access and location

```lua
ace = 'cc_images.foto',                       -- ACE for /ccfoto and every upload
studio = vector3(-4200.0, -4400.0, 900.0),     -- far out over the sea
bucket = 64000,                                -- each admin gets bucket + server ID
wetter = 'EXTRASUNNY',
uhrzeit = { 12, 0 },
ruhe = { aus = true, raeumen = 300.0, zuegeDanach = true },
```

| Option             | Meaning                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| `ruhe.aus`         | `false` = do not suppress traffic, peds, trains and boats during a session                       |
| `ruhe.raeumen`     | Radius (m) cleared at session start                                                              |
| `ruhe.zuegeDanach` | Re-enable random trains/boats afterwards; set `false` if another script disables them on purpose |

#### Background removal

```lua
verfahren = 'differenz',   -- 'differenz' (two shots, default) or 'chroma' (one shot)
hintergrund = { a = { 0, 190, 0 }, b = { 255, 0, 255 } },
chroma = { toleranz = 38, weich = 70 },   -- only for 'chroma'
```

#### Capture

```lua
greifer = 'auto',                             -- 'auto' | 'screenshot-basic' | 'eigen'
sbFormat = { encoding = 'png' },              -- lossless for keying
sbMessen = { encoding = 'jpg', quality = 0.8 },-- colour measuring only
umdrehen = false,                             -- true if images come out upside down
```

{% hint style="warning" %}
Keep `greifer = 'auto'`. The built-in grabber (`'eigen'`) returned only black images in testing; `'auto'` uses screenshot-basic whenever it is running.
{% endhint %}

#### Timing and upload

```lua
warten = { modell = 10000, erscheinen = 900, farbe = 300, speichern = 30000 },  -- ms
maxBytes = 1536 * 1024,   -- max upload size after decoding
uebertragung = 400000,    -- upload rate (bytes/s, latent event)
```

#### Image size and camera per type

Blocks `item`, `waffe` and `kleidung` define output size and camera: `breite`/`hoehe` (output pixels), `polster` (padding), `fov`, `winkel` (angle from front), `neigung` (tilt), `qualitaet` (WebP quality 0–1). `kleidung.component`, `kleidung.prop` and `kleidung.overlay` hold a camera per body zone; watches and bracelets use poses with a raised arm.

Presets saved with the camera editor (`/ccfoto kamera`) go to `config/kamera.json` and take priority over `config/foto.lua`. To remove one, delete the entry and `restart cc_images`.

#### Batches (`stapel`)

```lua
stapel = {
    texturFarben = true,    -- measure colour of every texture (~0.3 s each)
    texturenMax = 32,
    texturWarten = 80,      -- ms
    chatAlle = 25,          -- progress to chat every n pieces
    uploadsParallel = 3,
    katalogAlle = 50,       -- write clothing/index.json every n pieces
    neustart = true,        -- restart cc_images at the end (needs the restart ACE)
},
```

### Portrait (`Config.Portrait`)

```lua
Config.Portrait = {
    breite = 240, hoehe = 300,
    maxBytes = 30 * 1024,
    zeit = 15000,      -- max wait for TakePortrait (ms)
    abstand = 10000,   -- min time between two portraits of one player (ms)
    kamera = { abstand = 1.05, fov = 30.0, versatz = -0.06, augenhoehe = 0.03 },
    warten = 700,
    uebertragung = 150000,
}
```

### Other files

* `clothing/index.json` — catalogue for search and colour filter (written by `/ccfoto kleidung-alle`, can be edited by hand).
* `config/karte.lua` — settings of an internal capture mode not covered by this documentation.

## Exports, Events & Commands

### Image addresses

Interfaces load images directly via NUI URLs. All names are lowercase, `a–z`, `0–9`, `_` only.

| Type         | File                                                                       | URL                                               |
| ------------ | -------------------------------------------------------------------------- | ------------------------------------------------- |
| Item         | `items/<itemname>.webp`                                                    | `https://cfx-nui-cc_images/items/<itemname>.webp` |
| Clothing     | `clothing/<male\|female>/<component\|prop>_<nr>/<drawable>_<texture>.webp` | `https://cfx-nui-cc_images/clothing/…`            |
| Head overlay | `clothing/<male\|female>/overlay_<index>/<variant>_0.webp`                 | `https://cfx-nui-cc_images/clothing/…`            |
| Catalogue    | `clothing/index.json`                                                      | `https://cfx-nui-cc_images/clothing/index.json`   |

For clothing try `<d>_<t>.webp` → `<d>_0.webp` → placeholder, because batches store texture 0 by default.

### Commands

All `/ccfoto` commands require ACE `cc_images.foto` and cannot be used inside a vehicle.

| Command                                                                             | Effect                                                                                                                                       |
| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `/ccfoto item <name> <prop> [rotation]`                                             | Photograph item `<name>` using prop model `<prop>`                                                                                           |
| `/ccfoto items-fehlend [groups]`                                                    | All weapons, ammo, attachments/tints and food/drink from cc\_inventory **without** image; groups: `waffen`, `munition`, `aufsaetze`, `essen` |
| `/ccfoto items-alle [groups]`                                                       | Same, re-capturing existing images                                                                                                           |
| `/ccfoto kleidung <m\|f> <component\|prop> <nr> [from] [to] [texturen] [neu] [ped]` | One clothing zone; `texturen` = every colour as own image, `neu` = replace existing, `ped` = with ped                                        |
| `/ccfoto overlay <m\|f> <index> [from] [to] [neu]`                                  | Head overlays (0–12), one head image each                                                                                                    |
| `/ccfoto kleidung-alle [m\|f] [schnell] [neu]`                                      | All clothing and overlays of both models + catalogue, then restart                                                                           |
| `/ccfoto kleidung-alle erneut=m/c11/45,46,50-60`                                    | Re-capture exactly these pieces                                                                                                              |
| `/ccfoto kleidung-fehlend [nurbilder] [nur=…] [ohne=…] [ab=…]`                      | Only what is missing; never touches existing photos                                                                                          |
| `/ccfoto kamera <zone> [m\|f] [nr]`                                                 | Live camera editor (e.g. `p6` watches)                                                                                                       |
| `/ccfoto stopp`                                                                     | Stop after the current image                                                                                                                 |
| `/ccfoto neustart`                                                                  | Restart cc\_images so all players get new files                                                                                              |

Zone syntax for `nur=`, `ohne=`, `ab=`, `erneut=`: `c<nr>`/`component_<nr>`, `p<nr>`/`prop_<nr>`, `o<nr>`/`overlay_<nr>`, or whole categories `kleidung`, `props`, `overlays`; optional model prefix `m/` or `f/`.

**Camera editor keys:** arrows = angle/tilt, Page Up/Down = height, mouse wheel = framing, Q/E = FOV, Z/X = previous/next piece, Shift = 5× steps, R = reset, Enter = save, Backspace = exit.

### Server exports

#### TakePortrait(src) → data | false, code

Passport photo of a player. Must be called in a thread (event handler, `CreateThread`, callback); waits up to `Config.Portrait.zeit`.

```lua
local data, err = exports.cc_images:TakePortrait(src)
if not data then
    -- err: 'spieler' | 'laeuft' | 'rate' | 'studio' | 'kein_sb'
    --      | 'zeit' | 'format' | 'groesse' | 'client'
    return
end
-- data = 'data:image/webp;base64,…' (240 × 300, < 30 KB) — store it yourself
```

On failure the first value is `false`, not `nil` — always check `if not data then`. Nothing is saved by cc\_images. One portrait per player at a time, at most every `Config.Portrait.abstand` ms. The background is the real surroundings (no keying), so place the player in front of a wall first.

| Code                 | Meaning                                                          |
| -------------------- | ---------------------------------------------------------------- |
| `spieler`            | Invalid source or player left                                    |
| `laeuft`             | A portrait is already running for this player                    |
| `rate`               | Rate limit                                                       |
| `studio`             | Player is in the photo studio                                    |
| `kein_sb`            | screenshot-basic is not running                                  |
| `zeit`               | Timeout                                                          |
| `format` / `groesse` | Invalid image / too large                                        |
| `client`             | Camera/image/NUI failed on the client (reason in server console) |

#### Item images

| Export                                           | Returns                                                                                                               |
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `FotoItem(src, itemName, propModel?, rotation?)` | `ok, code` — starts a studio item shot for an admin; codes `recht`, `name`, `laeuft`, `fahrzeug`, `ok`                |
| `ItemBilder()`                                   | `{ stand, dateien = { name… }, frisch = { [name] = version }, voll }`                                                 |
| `ItemBildDaten(name)`                            | Base64 of a fresh image or `false`                                                                                    |
| `ItemBildSpeichern(name, base64)`                | `true, { bytes, breite, hoehe }` or `false, code` — WebP only, ≤ 512 KB, ≤ 1024 px; **the caller checks permissions** |
| `BildHolen(id, url, maxBytes)`                   | Downloads an https image with SSRF protection; result via server event `cc_images:bildGeholt`                         |
| `ItemBildVonUrl(url)`                            | Same, waiting for the result (call in a thread)                                                                       |

### Events

| Event                    | Side                           | Payload                                                  |
| ------------------------ | ------------------------------ | -------------------------------------------------------- |
| `cc_images:aktualisiert` | server (local) and all clients | `stand` — fired on start; reload cached images/catalogue |
| `cc_images:itemBild`     | server (local)                 | `name, version` — an item image is new or replaced       |
| `cc_images:bildGeholt`   | server (local)                 | `id, result` — answer to `BildHolen`                     |

## FAQ & Troubleshooting

**Why are there no images included?** cc\_images is a tool. Your admins create the images on your own server with the photo studio.

**New images are only visible to me.** FiveM reads a resource's file list at start; files written later are not sent to clients. The admin sees results immediately in the studio preview, everyone else after `restart cc_images` (or `/ccfoto neustart`). Tip: photograph a whole batch and restart once at the end. **Item images** are the exception — they show up immediately through cc\_inventory.

**`/ccfoto neustart` says it is not allowed.** Add `add_ace resource.cc_images command.restart allow` to `server.cfg`. A restart is also refused while someone is photographing.

**"The game image is black".** Start `screenshot-basic` before cc\_images and keep `Config.Foto.greifer = 'auto'`.

**"Background not detected".** Something covers the colour wall: open chat, another script's HUD, or a very large object.

**"Probably cut off".** Move the camera back in `config/foto.lua` (larger `fov`, or larger `radius` for clothing) — or use `/ccfoto kamera`.

**"Model unknown".** Check the spelling; addon models must be streamed.

**The image is upside down.** Set `Config.Foto.umdrehen = true`.

**A clothing batch was interrupted.** Just run the same command again — batches skip what already exists. Failed pieces are listed at the end and retried on the next run.

**How long does `/ccfoto kleidung-alle` take?** About 2 s per drawable plus \~0.3 s per extra texture — several hours for base-game clothing. Use `schnell` or `stapel.texturFarben = false` to roughly halve it.

**How big is the download for players?** Images are served via `files{}`, so players download the whole pool on first join (with all clothing roughly 50–80 MB), then from cache.

**`TakePortrait` returns `kein_sb`.** `screenshot-basic` is not running.

Still stuck? See Support.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://ccfivem.gitbook.io/ccfivem-docs/free-resources/image-studio-tool-cc_images.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
