===================================================================================================================
Trabalho de Computação Gráfica
===================================================================================================================
Autora: Cláudia Maria Caixeta Bezerra
Dithering
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
Este trabalho foi implementado na linguagem C utilizando o ambiente C++Builder.
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
O dithering é um processo de filtragem cuja finalidade é minimizar os efeitos percentuais do contorno de quantização, neste caso de dois níveis (1 bit).
A estratégia básica dos filtros de dithering consiste em distribuir o erro local de quantização por áreas da imagem de modo que, globalmente, ele se
anule (Gomes e Velho, 1994).
Um algoritmo básico é o dithering pontual ou limiar (threshold). Esta técnica consiste na escolha de um valor limiar e avaliando cada pixel da
imagem original tornando-os branco ou preto. Como na Figura abaixo onde tem-se a imagem original e a imagem limiarizada.
Implementação
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i,j,aux=0;
int *histog=(int *)calloc(256,sizeof(int));
pBitmap1 = new Graphics::TBitmap();
pBitmap2 = new Graphics::TBitmap();
Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;
pBitmap2->Height=pBitmap1->Height;
pBitmap2->Width=pBitmap1->Width;
pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap2->Assign(pBitmap1);
for (int x=0;x for (int y=0;y
{ //construção do histograma
aux=(int)Image1->Canvas->Pixels[x][y];
//cálculo para transformar Tcolor em nível de cinza
aux=((aux&255)+(aux&65280)/256+(aux&16711680)/65536)/3;
histog[aux]++;
}
}
for(int x1=0;x1 for(int y1=0;y1 if (((unsigned)pBitmap1->Canvas->Pixels[x1][y1] < RGB(128,128,128)))
pBitmap2->Canvas->Pixels[x1][y1]=clBlack;
else
pBitmap2->Canvas->Pixels[x1][y1]=clWhite;
}
}
Image2->Canvas->Draw(0,0,pBitmap2);
pBitmap1->FreeImage();
pBitmap2->FreeImage();
} //-------------------------------------------------------------------
Figura 1. a)Imagem original b)Imagem após a aplicação do dithering pontual.
//================================================================================================================== A pertubação aleatória somada à intensidade de cada pixel, descorrelaciona a intensidade do pixel da intensidade dos pixels vizinhos. Isso faz com que o contorno de quantização não seja uma curva conexa, dificultando a percepção da fronteira que separa duas regiões de quantização distintas.
Esse algoritmo é conhecido pelo nome de dithering por modulação aleatória (Gomes e Velho, 1994). Na Figura 2, aplicou-se este algoritmo na imagem original (Figura 1). Implementação
void __fastcall TForm1::Button2Click(TObject *Sender)
{
int i,j,aux2=0;
TColor tmp;
pBitmap1 = new Graphics::TBitmap();
pBitmap3 = new Graphics::TBitmap();
Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;
pBitmap3->Height=pBitmap1->Height;
pBitmap3->Width=pBitmap1->Width;
pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap3->Assign(pBitmap1);
for(int x1=0;x1 for(int y1=0;y1 aux2=random(255);
tmp=pBitmap3->Canvas->Pixels[x1][y1]+RGB(aux2, aux2, aux2);
if(tmp < RGB(128,128,128))
pBitmap3->Canvas->Pixels[x1][y1]=clBlack;
else
pBitmap3->Canvas->Pixels[x1][y1]=clWhite;
}
}
Image3->Canvas->Draw(0,0,pBitmap3);
pBitmap1->FreeImage();
pBitmap3->FreeImage();
}
//---------------------------------------------------------------------------
Figura 2. Dithering por modulação aleatória. //================================================================================================================== Em contraposição a estratégia de modulação aleatória, tem-se os algoritmos que produzem pertubações determinísticas.
ORDENADO PERIÓDICO (ESTRATÉGIA BÁSICA) Implementação
void __fastcall TForm1::Button3Click(TObject *Sender) pBitmap1 = new Graphics::TBitmap(); Image1->Width=pBitmap1->Width; pBitmap4->Height=pBitmap1->Height; pBitmap1->Assign(Image1->Picture->Bitmap); } Image4->Canvas->Draw(0,0,pBitmap4); pBitmap1->FreeImage(); A Figura 3 mostra a imagem resultante da implementação. Figura 3. Algoritmo ordenado periódico. //================================================================================================================== O dithering ordenado por dispersão faz uma distribuição dos limiares de quantização na matriz produzindo um efeito de transição suave entre as bandas obtidas em
relação ao dithering por aglomeração. A Figura 4 mostra os resultados da aplicação dos dois algoritmos ordenados periódicos na imagem original (Figura 1). Implementação
void __fastcall TForm1::Button4Click(TObject *Sender)
{
TColor Aux[2][2];
pBitmap1 = new Graphics::TBitmap();
pBitmap5 = new Graphics::TBitmap();
Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;
pBitmap5->Height=pBitmap1->Height;
pBitmap5->Width=pBitmap1->Width;
pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap5->Assign(pBitmap1);
Aux[0][0]=RGB(63,63,63);
Aux[0][1]=RGB(128,128,128);
Aux[1][0]=RGB(255,255,255);
Aux[1][1]=RGB(191,191,191);
for(int y1=0;y1 for(int x1=0;x1 if((pBitmap1->Canvas->Pixels[x1][y1])< (Aux[x1%2][y1%2]))
pBitmap5->Canvas->Pixels[x1][y1]=clBlack;
else
pBitmap5->Canvas->Pixels[x1][y1]=clWhite;
}
}
Image5->Canvas->Draw(0,0,pBitmap5);
pBitmap1->FreeImage();
pBitmap5->FreeImage();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender) pBitmap1 = new Graphics::TBitmap(); Image1->Width=pBitmap1->Width; pBitmap6->Height=pBitmap1->Height; pBitmap1->Assign(Image1->Picture->Bitmap); for(int y1=0;y1 Image6->Canvas->Draw(0,0,pBitmap6); pBitmap1->FreeImage(); }
Figura 4. a)Dispersed b)Clustered
//================================================================================================================== E por último vai ser mostrado, neste segundo trabalho, o dithering por difusão de erro--Floyd-Steinberg que é um dithering aperiódico. Ele calcula o
erro efetivo cometido na quantização de cada elemento e o distribui pelos seus vizinhos, tentando com isto minimizar o erro global. Pode ser visto na Figura a seguir
a aplicação deste algoritmo na imagem original (Figura 1).
Implementação
void __fastcall TForm1::Button6Click(TObject *Sender)
{
int aux=0;
TColor *erro=(TColor *)calloc(256,sizeof(TColor));
// erro = new Graphics::TBitmap();
pBitmap1 = new Graphics::TBitmap();
pBitmap7 = new Graphics::TBitmap();
Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;
pBitmap7->Height=pBitmap1->Height;
pBitmap7->Width=pBitmap1->Width;
pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap7->Assign(pBitmap1);
for(int x1=0;x1 for(int y1=0;y1 if(pBitmap1->Canvas->Pixels[x1][y1]<128) {
*erro=pBitmap1->Canvas->Pixels[x1][y1]-RGB(0,0,0);
// erro->Canvas->Pixels[x1][y1]=pBitmap1->Canvas->Pixels[x1][y1]-RGB(0,0,0);
pBitmap1->Canvas->Pixels[x1][y1]=clBlack;
}
else {
*erro=pBitmap1->Canvas->Pixels[x1][y1]-RGB(255,255,255);
pBitmap1->Canvas->Pixels[x1][y1]=clWhite;
}
if (y1 < Height)
pBitmap7->Canvas->Pixels[x1][y1+1]=pBitmap7->Canvas->Pixels[x1][y1+1]+(7*(*erro)/16);
if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)
pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;
}
if ((x1 < Width) && (y1 < Height)){
pBitmap7->Canvas->Pixels[x1+1][y1+1]=pBitmap7->Canvas->Pixels[x1+1][y1+1]+((*erro)/16);
if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)
pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;
}
if (x1 < Width){ pBitmap7->Canvas->Pixels[x1+1][y1]=pBitmap7->Canvas->Pixels[x1+1][y1]+(5*(*erro)/16);
if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)
pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;
}
if ((x1 < Width) && (y1 > 1)){
pBitmap7->Canvas->Pixels[x1+1][y1-1]=pBitmap7->Canvas->Pixels[x1+1][y1-1]+(3*(*erro)/16);
if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)
pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;
}
}
}
Image7->Canvas->Draw(0,0,pBitmap7);
pBitmap1->FreeImage();
pBitmap7->FreeImage();
delete erro;
}
//---------------------------------------------------------------------------
Figura 5. Dithering Floyd-Steinberg. //================================================================================================================== Na Figura 6 pode-se ver a aplicação, na imagem original, de todos os algoritmos abordados neste trabalho. Figura 6. Imagens mostrando todas as aplicação dos algoritmos aqui expostos. //================================================================================================================== Código Código(Unit) Aplicativo Dithering.exe(zippado) Arquivo Dithering(zip) //------------------------------------------------------------------------------------------------------------------------------------------------------------------- Pg
Inicial Visão Geral
{
int i,j, aux=0;
TColor tmp;
pBitmap4 = new Graphics::TBitmap();
Image1->Height=pBitmap1->Height;
pBitmap4->Width=pBitmap1->Width;
pBitmap4->Assign(pBitmap1);
for(int x1=0;x1
for(int y1=0;y1
i=x1%4;
j=y1%4;
if(pBitmap1->Canvas->Pixels[x1][y1]>pBitmap1->Canvas->Pixels[i][j])
pBitmap4->Canvas->Pixels[x1][y1]=clWhite;
else
pBitmap4->Canvas->Pixels[x1][y1]=clBlack;
}
pBitmap4->FreeImage();
}
//---------------------------------------------------------------------------
{
TColor Vec[2][2];
pBitmap6 = new Graphics::TBitmap();
Image1->Height=pBitmap1->Height;
pBitmap6->Width=pBitmap1->Width;
pBitmap6->Assign(pBitmap1);
Vec[0][0]=RGB(63,63,63);
Vec[0][1]=RGB(191,191,191);
Vec[1][0]=RGB(255,255,255);
Vec[1][1]=RGB(128,128,128);
for(int x1=0;x1
if((pBitmap1->Canvas->Pixels[x1][y1])< (Vec[x1%2][y1%2]))
pBitmap6->Canvas->Pixels[x1][y1]=clBlack;
else
pBitmap6->Canvas->Pixels[x1][y1]=clWhite;
}
}
pBitmap6->FreeImage();
//---------------------------------------------------------------------------