DirectBitmap & Buffer Bgra32 (Análise do Código)
A classe DirectBitmap.cs é a base de manipulação de memória de todo o laboratório. Abaixo está a análise detalhada de seu funcionamento.
1. Estrutura da Classe
namespace CGPDI.StudyLab.Core{ public sealed unsafe class DirectBitmap : IDisposable { public int Width { get; } public int Height { get; } public int Stride { get; } public WriteableBitmap Bitmap { get; }
private byte* _backBuffer; private bool _isLocked; private bool _disposed; }}sealed: Impede herança, permitindo otimizações de compilação JIT.unsafe: Permite o uso de ponteiros de memória direta (byte*).IDisposable: Assegura a liberação adequada dos recursos nativos.
2. Métodos de Bloqueio: Lock() e Unlock()
Antes de alterar os pixels, precisamos fixar o buffer na memória RAM para que o Garbage Collector não altere seu endereço durante a execução:
public void Lock(){ if (!_isLocked) { Bitmap.Lock(); _backBuffer = (byte*)Bitmap.BackBuffer.ToPointer(); _isLocked = true; }}Ao término, o buffer é liberado e o subsistema gráfico é notificado para atualizar a janela:
public void Unlock(bool markDirty = true){ if (_isLocked) { if (markDirty) { // Notifica o DirectX que a area da imagem foi alterada Bitmap.AddDirtyRect(new Int32Rect(0, 0, Width, Height)); } Bitmap.Unlock(); _backBuffer = null; _isLocked = false; }}3. Escrita de Pixels Otimizada
[MethodImpl(MethodImplOptions.AggressiveInlining)]public void SetPixel(int x, int y, Color color){ if (x < 0 || x >= Width || y < 0 || y >= Height) return;
byte* pixelPtr = _backBuffer + (y * Stride) + (x * 4); pixelPtr[0] = color.B; // Blue (Azul) pixelPtr[1] = color.G; // Green (Verde) pixelPtr[2] = color.R; // Red (Vermelho) pixelPtr[3] = color.A; // Alpha (Opacidade)}4. Paralelismo Multinúcleo com Parallel.For
A Analogia da Equipe de Pintores:
Se uma única pessoa pintar uma parede de 512 linhas, ela levará muito tempo. Se contratarmos uma equipe de 8 pintores, cada um pinta uma faixa horizontal da parede ao mesmo tempo:
Parallel.For(0, Height, y =>{ byte* srcRow = src.BackBuffer + (y * src.Stride); byte* dstRow = dst.BackBuffer + (y * dst.Stride);
for (int x = 0; x < Width; x++) { int idx = x * 4; byte b = srcRow[idx + 0]; byte g = srcRow[idx + 1]; byte r = srcRow[idx + 2];
// Calculo de escala de cinza perceptiva byte cinza = (byte)((r * 2126 + g * 7152 + b * 722) / 10000);
dstRow[idx + 0] = cinza; // B dstRow[idx + 1] = cinza; // G dstRow[idx + 2] = cinza; // R dstRow[idx + 3] = 255; // A }});📚 Referências Oficiais Microsoft Learn
Consulte a documentação técnica da API da Microsoft utilizada nesta implementação:
- Classe WriteableBitmap (System.Windows.Media.Imaging) — Métodos
Lock(),Unlock(),AddDirtyRect()e propriedadeBackBuffer. - Enumeração MethodImplOptions — Otimizações do JIT como
AggressiveInliningeAggressiveOptimization. - PixelFormats.Bgra32 Property — Especificação técnica do formato de cor nativo de 32 bits no WPF.
👉 Próximo Passo: Explore os Modelos de Cores & Percepção Humana.