# Correção — upload de imagens (GD / libpng iCCP)

Documento de referência para o erro **500 em produção** ao enviar favicon, logo ou fundo em **Configurações → Aparência do portal** (e processamento equivalente no questionário game).

**Última atualização:** 2026-05-18.

---

## Sintoma em produção

- **Rota:** `PUT /settings/portal-appearance` (ou upload de logo/favicon nas configurações).
- **HTTP:** 500 Internal Server Error.
- **Exceção (Ignition / log):**

```text
ErrorException
imagecreatefrompng(): gd-png: libpng warning: iCCP: known incorrect sRGB profile
```

- **Ficheiro apontado:** `app/Support/PortalFaviconNormalizer.php` (linha do `imagecreatefrompng`), ou o mesmo fluxo via `RasterLogoBackgroundNormalizer` para logos.

---

## Causa

1. Muitos PNGs exportados (Photoshop, Figma, Canva, etc.) incluem um chunk de perfil de cor **iCCP** que o **libpng** considera inválido ou inconsistente.
2. O **GD** do PHP emite um **warning** (não um erro fatal) ao carregar o ficheiro.
3. Em **produção**, o handler de erros do Laravel costuma **promover warnings a `ErrorException`**, interrompendo o request mesmo quando a imagem seria carregada com sucesso.

**Importante:** o ficheiro PNG em si costuma estar correto; o problema é o tratamento do aviso no servidor, não um upload inválido.

---

## Solução implementada

Foi introduzida a classe **`App\Support\GdImageFactory`**, responsável por carregar imagens raster via GD **suprimindo apenas avisos benignos** do libpng/GD (incluindo `iCCP`, `gd-png`, `gd-jpeg`, `gd-webp`).

### Onde é usada

| Classe | Uso |
|--------|-----|
| `PortalFaviconNormalizer` | Favicon → PNG 32×32 |
| `RasterLogoBackgroundNormalizer` | Logo/fundo — remoção de fundo claro nas bordas |
| `StoredRasterLogoProcessor` | Gravação no disco (indireto, via `RasterLogoBackgroundNormalizer`) |

### Comportamento

- O upload **continua a processar** a imagem normalmente.
- Avisos reais ou falhas de leitura **não** são mascarados de forma genérica: o handler só ignora mensagens conhecidas do GD/libpng ligadas a perfil/código de aviso.
- Se `imagecreatefrompng` falhar de verdade, o retorno permanece `false` e o fluxo do service trata como antes (fallback ou erro explícito).

---

## Arquivos do patch

| Arquivo | Alteração |
|---------|-----------|
| `app/Support/GdImageFactory.php` | **Criado** — factory com `fromPng`, `fromJpeg`, `fromGif`, `fromWebp`, `fromPath` |
| `app/Support/PortalFaviconNormalizer.php` | `createImageResource()` delega a `GdImageFactory` |
| `app/Support/RasterLogoBackgroundNormalizer.php` | Idem |
| `tests/Unit/Support/GdImageFactoryTest.php` | Teste unitário (requer extensão GD) |

---

## Deploy

1. Publicar o código com `GdImageFactory` e as alterações nos normalizers.
2. **Não** é necessária migration.
3. **Não** é necessário `npm run build` (só PHP).
4. Opcional: `php artisan config:cache` após deploy.

```bash
composer install --no-dev --optimize-autoloader
# reiniciar PHP-FPM / workers se aplicável
```

---

## Verificação pós-deploy

1. **Gestão** → Configurações → Aparência do portal.
2. Enviar o **mesmo PNG** que falhava antes (favicon ou logo).
3. Confirmar gravação com mensagem de sucesso e preview na página.
4. Repetir com **JPEG** e **WebP** se forem usados no ambiente.

Teste automatizado local:

```bash
php artisan test --filter=GdImageFactoryTest
```

---

## Alternativas (não necessárias após o patch)

| Abordagem | Nota |
|-----------|------|
| Re-exportar PNG sem perfil iCCP | Funciona, mas obriga o utilizador; o sistema deve aceitar PNGs comuns |
| `@imagecreatefrompng()` | Suprime no PHP mas o handler do Laravel ainda pode capturar o warning |
| Desativar conversão de warnings em produção | Arriscado — esconde outros problemas |

---

## Documentos relacionados

- [deploy-producao-questionario-experiencia.md](./deploy-producao-questionario-experiencia.md) — secção 9 (logos e GD)
- [registro-entregas.md](./registro-entregas.md) — registo por data desta correção
