🎨 Editor de Imagens (Paint)#

Editor de imagens integrado, inspirado no Paint clássico. Funciona embutido no Codis ou standalone.

Arquitetura (separada para ser testável): src/ui/paint_engine.py (motor, sem Tk) · src/ui/paint_canvas.py (canvas) · src/ui/paint_panel.py (barra de ferramentas, paleta, arquivos).

Abrindo#

  • Menu Ferramentas → Editor de Imagens, ou duplo clique em .png/.jpg/.bmp/.gif/.webp na árvore de arquivos.
  • Linha de comando: python run.py --paint [imagem.png]

Ferramentas#

Ferramenta Comportamento
Pincel Antialiasing real; a opacidade não acumula dentro do mesmo traço
Pixel Traço sem suavização (pixel art)
Spray Aerógrafo acumulativo
Borracha Apaga com a cor de fundo (botão direito: cor primária)
Balde Preenchimento com tolerância; Ctrl+clique preenche todas as áreas parecidas (não só a conectada)
Linha / Retângulo / Elipse Com antialiasing; Shift = 45° / quadrado / círculo; "Preencher" preenche
Polígono Clique adiciona pontos; duplo clique/Enter fecha; Esc cancela
Texto Fonte do sistema (DejaVu/Arial/…) com antialiasing
Conta-gotas Botão esquerdo = cor primária, direito = secundária
Seleção Retângulo; arraste de dentro para mover (deixa a cor de fundo no lugar); Ctrl+C/X/V, Delete, Ctrl+A
Pan (mão) Arrasta a imagem

Atalhos#

Atalho Ação
Ctrl+Z / Ctrl+Y (ou Ctrl+Shift+Z) Desfazer / refazer
Ctrl+S / Ctrl+Shift+S / Ctrl+O / Ctrl+N Salvar / salvar como / abrir / novo
Ctrl+C / Ctrl+X / Ctrl+V / Ctrl+A Copiar / recortar / colar (aceita imagem da área de transferência do sistema, quando a plataforma permite) / selecionar tudo
Roda Rola na vertical · Shift+roda horizontal · Ctrl+roda zoom no cursor
Botão do meio ou Espaço+arrastar Pan
+ / - / Ctrl+0 Zoom / ajustar à janela
Esc Cancela o traço, a seleção flutuante ou o polígono

O zoom vai de 6% a 3200%; a grade de pixels aparece a partir de 800%. O título mostra • quando há alterações não salvas e Novo/Abrir perguntam antes de descartar.

Desempenho (por que não trava mais)#

Medido no mesmo script antes/depois (800×600 | 4000×3000):

Operação Antes Depois
Evento de pincel 22 ms | 650 ms 2 ms | 1,6 ms
Evento de pincel com zoom 8× (grade) 844 ms ~1 ms
Balde numa imagem em branco 1.180 ms | minutos 37 ms | 560 ms
Zoom 8× em 4000×3000 estourava a memória 17 ms
Undo 33 ms (+PNG inteiro por ação) 8 ms (só blocos alterados)

Como: renderiza só o retângulo visível/sujo (sem reescalar a imagem inteira nem criar milhares de itens de canvas para a grade/xadrez); eventos de mouse são coalescidos em um desenho por ciclo ocioso; o pincel acumula uma máscara e compõe só a caixa afetada; o balde trabalha por trechos horizontais; o histórico guarda blocos de 256×256 (limite de ~384 MB, 200 ações).

Salvando#

PNG/WebP preservam transparência. JPEG/BMP achatam sobre branco (antes ficava preto onde era transparente). A gravação é atômica (arquivo temporário + replace): uma falha não corrompe o original. Imagens com orientação EXIF são giradas ao abrir.

Testes#

tests/test_paint_engine.py (motor: undo contra snapshots, flood fill contra BFS de referência, renderização parcial == total, orçamentos de tempo) e tests_gui/test_paint_canvas.py (compara os pixels exibidos com o modelo).