Skip to content

Aceitar PNG/WebP e melhorar mensagem de erro para JPEG progressivo (icebox - melhorias DX) #45

Description

@rhfranzoni

Origem

@rhfranzoni via Claude Code (conversa interna 2026-05-28) — sub-issue derivada da issue mãe em nfe/dfetech-product-invoice-api. Marcada como icebox / não bloqueia MVP — a integração end-to-end de logo na DANFE funciona sem nenhuma alteração no DanfeSharp (a API atual já é suficiente). Esta sub-issue cobre dois pontos de polimento.

Contexto

A biblioteca DanfeSharp já oferece API funcional para injeção de logo no DANFE via Danfe.cs:86-123AdicionarLogoImagem(Stream) e AdicionarLogoPdf(Stream). Renderiza em todas as páginas via XObject único (custo de bytes mínimo) com posicionamento adaptativo (horizontal → max 14pt altura; vertical → scaled to container).

Duas limitações conhecidas que valem ser tratadas em um momento futuro:

  1. Sem suporte a PNG/WebP nativo. A lib aceita apenas JPEG não-progressivo ou PDF (first page). PNG falha com InvalidOperationException lançada em Danfe.cs:91. A solução em produção contorna isso convertendo na ingestão (dfetech-tax-payers-api re-encoda para JPEG não-progressivo via ImageSharp) — funciona perfeitamente para o caso NFe.IO. Mas para consumers externos do DanfeSharp (a lib é open-source / pode ter consumidores fora da NFe.IO), suportar PNG e WebP nativamente seria uma melhoria importante de DX.

  2. Mensagem de erro genérica para JPEG progressivo. Quando o usuário tenta carregar um JPEG progressivo (codificação SOF2 em vez de SOF0 baseline), a mensagem atual é "O logotipo não pode ser carregado, certifique-se que a imagem esteja no formato JPEG não progressivo". Não há detecção ativa do marker SOF — o erro vem do PdfClown ao falhar no parse, e a mensagem é uma adivinhação razoável mas genérica. Idealmente queremos: detectar o marker SOF (0xFFC2 = progressive, 0xFFC0 = baseline) no header do JPEG antes de passar para o PdfClown, dando erro descritivo ("JPEG progressivo detectado (marker SOF2). DanfeSharp suporta apenas JPEG baseline (SOF0). Re-encode com 'jpegtran -copy none -optimize source.jpg dest.jpg' ou Pillow Image.save(progressive=False).").

Nenhuma dessas duas é crítica — ambas têm workaround. Por isso a issue fica como icebox.

Objetivo

(1) Suportar PNG e WebP como formatos de entrada nativos do AdicionarLogoImagem(Stream) — usuários da biblioteca podem passar PNG sem precisar pré-converter. (2) Quando o usuário passa um JPEG progressivo, a exception lançada inclui mensagem descritiva com diagnóstico do marker SOF detectado e sugestão concreta de comando para corrigir.

Escopo — Inclui

  • PNG/WebP support (item 1):
    • Investigar capability atual do PdfClown.NetStandard 0.2.0-beta para PNG (org.pdfclown.documents.contents.entities.Image.Get)
    • Se PdfClown não suporta nativamente: adicionar conversão inline via SixLabors.ImageSharp (mesma biblioteca usada no dfetech-tax-payers-api) antes de passar para Image.Get
    • Fixture nova: DanfeSharp.Test/Logos/PNG/Quadrado.png (e Horizontal/Vertical)
    • Tests novos em DanfeXmlTests ou novo LogoFormatTests.cs: gerar DANFE com PNG e verificar via PdfClown TextExtractor (a área do emitente preservada) + verificar XObject embedded
  • JPEG progressivo diagnostic (item 2):
    • Helper privado DetectJpegEncoding(Stream): peek nos primeiros bytes do stream, procurar marker SOF (0xFFC0 = baseline, 0xFFC2 = progressive), restaurar position do stream
    • Em AdicionarLogoImagem(Stream): se source for JPEG, chamar DetectJpegEncoding antes do Image.Get. Se progressive → lançar InvalidOperationException descritiva (com marker, sugestão de comando, link para issue)
    • Test: passar JPEG progressivo conhecido → verificar mensagem da exception
  • Documentação (README.md da lib):
    • Seção "Formatos suportados" com tabela: JPEG baseline (✓), JPEG progressive (✗ com explicação), PNG (✓ após esta change), WebP (✓ após esta change), PDF (✓)
    • Snippet de exemplo de uso de AdicionarLogoImagem(Stream)

Escopo — Não inclui

  • Suporte a SVG (requer raster intermediate, fora de scope)
  • Suporte a animated GIF / multi-frame imagens (DANFE é estático, sem sentido)
  • Mudança no posicionamento do logo na DANFE (já funciona)
  • Mudança no comportamento de PDF logo (já funciona)
  • Upgrade major do PdfClown (risco alto, escopo amplo — fazer separadamente se necessário)

Critérios de Aceitação

  • danfe.AdicionarLogoImagem(streamPng) carrega um PNG e renderiza no DANFE corretamente
  • danfe.AdicionarLogoImagem(streamWebp) carrega um WebP e renderiza no DANFE corretamente
  • danfe.AdicionarLogoImagem(streamJpgProgressive) lança InvalidOperationException com mensagem mencionando explicitamente "JPEG progressivo" e o marker SOF2 detectado
  • Mensagem da exception inclui pelo menos uma sugestão concreta de comando (jpegtran ou Pillow) para converter para baseline
  • Tests cobrindo PNG, WebP, JPEG baseline, JPEG progressive e PDF
  • README atualizado com tabela de formatos suportados e snippet de uso
  • Zero regressão em fixtures existentes (Quadrado.jpg, Horizontal.jpg, Vertical.jpg, Quadrado.pdf, Horizontal.pdf, Vertical.pdf — todos continuam funcionando)
  • dfetech-tax-payers-api continua convertendo para JPEG baseline na ingestão (não precisa mudar — a conversão estabiliza o formato, mesmo com DanfeSharp suportando PNG/WebP nativamente, é boa prática manter formato canônico no storage)

Dependências

  • Nenhuma — esta sub-issue é independente da issue mãe e da sub-issue de tax-payers-api
  • Não bloqueia o MVP — a feature de logo na DANFE funciona integralmente sem esta sub-issue

Referências


Classificação (Project Fields)

Priority: Medium
Compliance: Não — melhoria de DX da biblioteca, sem mandato fiscal

Follow-up

  • Templates de issue ausentes em nfe/DanfeSharp — considerar bootstrap futuramente
  • Avaliar se vale upgrade do PdfClown.NetStandard de 0.2.0-beta para versão estável (escopo separado, risco maior)
  • Se PNG support requerer ImageSharp como dependência, validar licença Split License da v3

Metadata

Metadata

Assignees

Labels

origem:produtoDemanda originada de análise técnica/produto interno

Fields

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions