//图像灰度均衡
int GrayEqualize(BYTE *image,DWORD dwWidth,DWORD dwHeight,WORD wBitCount)
{
DWORD height=dwHeight;
DWORD width=dwWidth;
WORD bitCount=wBitCount;
DWORD lineBytes=(width*bitCount+31)/32*4;
BYTE *temp=image;
BYTE grayMap[256];
DWORD grayNum[256];
BYTE BgrayMap[256];
DWORD BgrayNum[256];
BYTE GgrayMap[256];
DWORD GgrayNum[256];
BYTE RgrayMap[256];
DWORD RgrayNum[256];
DWORD i=0;
DWORD j=0;
int n=0;
int m=0;
BYTE b=0;
BYTE g=0;
BYTE r=0;
long c=0;
long bc=0,gc=0,rc=0;
if(temp==NULL)
{
return -1;
}
for(n=0;n<256;n++)
{
grayNum[n]=0;
grayMap[n]=0;
BgrayNum[n]=0;
BgrayMap[n]=0;
GgrayNum[n]=0;
GgrayMap[n]=0;
RgrayNum[n]=0;
RgrayMap[n]=0;
}
if(bitCount==8)
{
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
g=*(temp+lineBytes*(height-1-i)+j);
grayNum[g]++;
}
}
for(n=0;n<256;n++)
{
c=0;
for(m=0;m<=n;m++)
{
c+=grayNum[m];
}
grayMap[n]=(BYTE)(c*255/height/width);
}
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
g=*(temp+lineBytes*(height-1-i)+j);
*(temp+lineBytes*(height-1-i)+j)=grayMap[g];
}
}
}
else if(bitCount==24)
{
for(i=0;i<height;i++)
{
for(j=0;j<width*3;j++)
{
b=*(temp+lineBytes*(height-1-i)+j);
j++;
g=*(temp+lineBytes*(height-1-i)+j);
j++;
r=*(temp+lineBytes*(height-1-i)+j);
BgrayNum[b]++;
GgrayNum[g]++;
RgrayNum[r]++;
}
}
for(n=0;n<256;n++)
{
bc=0;gc=0;rc=0;
for(m=0;m<=n;m++)
{
bc+=BgrayNum[m];
gc+=GgrayNum[m];
rc+=RgrayNum[m];
}
BgrayMap[n]=(BYTE)(bc*255/height/width);
GgrayMap[n]=(BYTE)(gc*255/height/width);
RgrayMap[n]=(BYTE)(rc*255/height/width);
}
for(i=0;i<height;i++)
{
for(j=0,n=0;j<width*3;j++,n++)
{
b=*(temp+lineBytes*(height-1-i)+j);
j++;
g=*(temp+lineBytes*(height-1-i)+j);
j++;
r=*(temp+lineBytes*(height-1-i)+j);
*(temp+lineBytes*(height-1-i)+n)=BgrayMap[b];
n++;
*(temp+lineBytes*(height-1-i)+n)=GgrayMap[g];
n++;
*(temp+lineBytes*(height-1-i)+n)=RgrayMap[r];
}
}
}
else
{
return -1;
}
return 0;
}
//图像线性灰度变换
int LineTranslation(BYTE *image,DWORD dwWidth,DWORD dwHeight,
WORD wBitCount,double k,double d)
{
DWORD dwLineBytes=(dwWidth*wBitCount+31)/32*4;
DWORD i=0;
DWORD j=0;
DWORD n=0;
BYTE b=0;
BYTE g=0;
BYTE r=0;
double nb=0;
double ng=0;
double nr=0;
double f=0;
if(image==NULL)
{
return -1;
}
if(wBitCount==8)
{
for(i=0;i<dwHeight;i++)
{
for(j=0;j<dwWidth;j++)
{
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
f=g*k+d;
if(f>255) f=255;
if(f<0) f=0;
*(image+dwLineBytes*(dwHeight-1-i)+j)=(BYTE)f;
}
}
}
else if(wBitCount==24)
{
for(i=0;i<dwHeight;i++)
{
for(j=0,n=0;j<dwWidth*3;j++,n++)
{
b=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
r=*(image+dwLineBytes*(dwHeight-1-i)+j);
nb=b*k+d;
if(nb>255) nb=255;
if(nb<0) nb=0;
ng=g*k+d;
if(ng>255) ng=255;
if(ng<0) ng=0;
nr=r*k+d;
if(nr>255) nr=255;
if(nr<0) nr=0;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)nb;
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)ng;
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)nr;
}
}
}
else
{
return -1;
}
return 0;
}
//图像灰度拉伸变换
int GrayStretch(BYTE* image,DWORD dwWidth,DWORD dwHeight,WORD wBitCount,
int pt1x,int pt1y,int pt2x,int pt2y)
{
BYTE map[256];
int n=0;
DWORD dwLineBytes=(dwWidth*wBitCount+31)/32*4;
DWORD i=0;
DWORD j=0;
BYTE b=0;
BYTE g=0;
BYTE r=0;
double avg=0.0;
int ag=0;
if(image==NULL)
{
return -1;
}
for(n=0;n<=pt1x;n++)
{
if(pt1x>0)
{
map[n]=(BYTE)pt1y*n/pt1x;
}
else
{
map[n]=0;
}
}
for(;n<=pt2x;n++)
{
if(pt2x!=pt1x)
{
map[n]=pt1y+(BYTE)((pt2y-pt1y)*(n-pt1x)/(pt2x-pt1x));
}
else
{
map[n]=pt1y;
}
}
for(;n<256;n++)
{
if(pt2x!=255)
{
map[n]=pt2y+(BYTE)((255-pt2y)*(n-pt2x)/(255-pt2x));
}
else
{
map[n]=255;
}
}
if(wBitCount==8)
{
for(i=0;i<dwHeight;i++)
{
for(j=0;j<dwWidth;j++)
{
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
*(image+dwLineBytes*(dwHeight-1-i)+j)=map[g];
}
}
}
else if(wBitCount==24)
{
for(i=0;i<dwHeight;i++)
{
for(j=0,n=0;j<dwWidth*3;j++,n++)
{
b=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
r=*(image+dwLineBytes*(dwHeight-1-i)+j);
avg=(b+g+r)/3.0;
ag=(int)avg;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)map[ag];
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)map[ag];
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)map[ag];
}
}
}
else
{
return -1;
}
return 0;
}
//图像阈值变换
int ThresholdTranslation(BYTE* image,DWORD dwWidth,DWORD dwHeight,
WORD wBitCount,BYTE bytThreshold)
{
DWORD i=0;
DWORD j=0;
DWORD n=0;
BYTE b=0;
BYTE g=0;
BYTE r=0;
double avg=0.0;
DWORD dwLineBytes=(dwWidth*wBitCount+31)/32*4;
if(wBitCount==8)
{
for(i=0;i<dwHeight;i++)
{
for(j=0;j<dwWidth;j++)
{
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
if(g<bytThreshold)
{
*(image+dwLineBytes*(dwHeight-1-i)+j)=0;
}
else
{
*(image+dwLineBytes*(dwHeight-1-i)+j)=255;
}
}
}
}
else if(wBitCount==24)
{
for(i=0;i<dwHeight;i++)
{
for(j=0,n=0;j<dwWidth*3;j++,n++)
{
b=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
g=*(image+dwLineBytes*(dwHeight-1-i)+j);
j++;
r=*(image+dwLineBytes*(dwHeight-1-i)+j);
avg=(b+g+r)/3.0;
if(avg<bytThreshold)
{
avg=0;
}
else
{
avg=255;
}
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)avg;
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)avg;
n++;
*(image+dwLineBytes*(dwHeight-1-i)+n)=(BYTE)avg;
}
}
}
else
{
return -1;
}
return 0;
}
#endif
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "Bitmap.h"
#include "Algorithm.h"
int main(int argc,char **argv)
{
char image_path[256];
char save_path[256];
int ret=0;
DWORD dwHeight=0;
DWORD dwWidth=0;
WORD wBitCount=0;
int select=0;
bool con=TRUE;
int pt1x,pt1y,pt2x,pt2y;
double k=0,d=0;
int p=0,t=0;
if(argc==2)
{
memcpy(image_path,argv[1],256*sizeof(char));
}
else
{
printf("Please input the path of the bitmap(.bmp):\n");
scanf("%s",image_path);
}
ret=TIMage_Read(image_path);
if(ret!=0)
{
printf("FAILED: read the bitmap %s.\n",image_path);
return -1;
}
dwHeight=TIMage_GetHeight();
dwWidth=TIMage_GetWidth();
wBitCount=TIMage_GetBitCount();
while(con==TRUE)
{
printf("-----Main Menu-----\n");
printf(" 1. GrayEqualize\n");
printf(" 2. GrayStretch\n");
printf(" 3. LineTranslation\n");
printf(" 4. LogTranslation\n");
printf(" 5. ThresholdTranslation\n");
printf(" 6. WindowTranslation\n");
printf(" 7. Erosion\n");
printf(" 8. Dilation\n");
printf(" 9. Open\n");
printf(" 10. Close\n");
printf(" 11. Thining.\n");
printf("99. Save the BITMAP\n");
printf(" 0. EXIT\n");
scanf("%d",&select);
switch(select)
{
case 0:
con=FALSE;
break;
case 1://GrayEqualize
ret=GrayEqualize(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount);
if(ret==-1)
{
printf("FAILED: GrayEqulaize.\n");
con=FALSE;
break;
}
printf("Successed: GrayEqualize.\n");
break;
case 2://GrayStretch
printf("Input the coordinate of two point(pt1x,pt1y,pt2x,pt2y):\n");
scanf("%d,%d,%d,%d",&pt1x,&pt1y,&pt2x,&pt2y);
ret=GrayStretch(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,pt1x,pt1y,pt2x,pt2y);
if(ret==-1)
{
printf("FAILED: GrayStretch.\n");
con=FALSE;
break;
}
printf("Successed: GrayStretch.\n");
break;
case 3://LineTranslation
printf("Input k,d:\n");
scanf("%d,%d",&k,&d);
ret=LineTranslation(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,k,d);
if(ret==-1)
{
printf("FAILED: LineTranslation.\n");
con=FALSE;
break;
}
printf("Successed: LineTranslation.\n");
break;
case 4://LogTranslation
printf("Input k:\n");
scanf("%d",&p);
ret=LogTranslation(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,p);
if(ret==-1)
{
printf("FAILED: LogTranslation.\n");
con=FALSE;
break;
}
printf("Successed: LogTranslation.\n");
break;
case 5://ThresholdTranslation
printf("Input the Threshold:\n");
scanf("%d",&p);
ret=ThresholdTranslation(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,p);
if(ret==-1)
{
printf("FAILED: ThresholdTranslation.\n");
con=FALSE;
break;
}
printf("Successed: ThresholdTranslation.\n");
break;
case 6://WindowTranslation
printf("Input the down and up Value(down,up):\n");
scanf("%d,%d",&p,&t);
ret=WindowTranslation(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,p,t);
if(ret==-1)
{
printf("FAILED: WindowTranslation.\n");
con=FALSE;
break;
}
printf("Successed: WindowTranslation.\n");
break;
case 7://Erosion
printf("Direction: 0-Horizontal 1-Vertically\n");
scanf("%d",&p);
printf("Element Size: 3 or 5 or 7\n");
scanf("%d",&t);
ret=Erosion(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,p,t);
if(ret==-1)
{
printf("FAILED: Erosion.\n");
con=FALSE;
break;
}
printf("Successed: Erosion.\n");
break;
case 8://Dilation
printf("Direction: 0-Horizontal 1-Vertically\n");
scanf("%d",&p);
printf("Element Size: 3 or 5 or 7\n");
scanf("%d",&t);
ret=Dilation(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,p,t);
if(ret==-1)
{
printf("FAILED: Dilation.\n");
con=FALSE;
break;
}
printf("Successed: Dilation.\n");
break;
case 9:
printf("Direction: 0-Horizontal 1-Vertically\n");
scanf("%d",&p);
printf("Element Size: 3 or 5 or 7\n");
scanf("%d",&t);
ret=OpenClose(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,0,p,t);
if(ret==-1)
{
printf("FAILED: Open.\n");
con=FALSE;
break;
}
printf("Successed: Open.\n");
break;
case 10:
printf("Direction: 0-Horizontal 1-Vertically\n");
scanf("%d",&p);
printf("Element Size: 3 or 5 or 7\n");
scanf("%d",&t);
ret=OpenClose(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount,1,p,t);
if(ret==-1)
{
printf("FAILED: Close.\n");
con=FALSE;
break;
}
printf("Successed: Close.\n");
break;
case 11:
ret=Thining(TIMagePixelMatrix,dwWidth,dwHeight,wBitCount);
if(ret==-1)
{
printf("FAILED: Thining.\n");
con=FALSE;
break;
}
printf("Successed: Thining.\n");
break;
case 99://Save the image to a bitmap file
printf("Please input the path you want to save the bitmap(.bmp):\n");
scanf("%s",save_path);
ret=TIMage_Write(save_path);
if(ret!=0)
{
printf("FAILED: save the bitmap %s.\n",save_path);
con=FALSE;
return -1;
}
printf("Successed to save the bitmap.\n");
break;
default:
con=FALSE;
break;
}
}
return 0;
}