其实在第二节我们已经介绍了调色板,在那里我们将图像进行了反色,我们采用的其中一种方法是把调色板
进行反色。
在这里我们介绍一下如何在调色板里保留一些颜色,这样我们可以在图像上画图,有利于显示。
先介绍我们这一期的画图函数
描绘细节点函数(细节点是指纹中的一个概念,在后续文章中会介绍)
,这个函数可以指定一个坐标位置x,y,把图像上这个点的附近画一个小圆圈。
像素值是1。
void paint_min(unsigned char *pImg, int x, int y, int w, int h)
{
if(x<2 || y<2 || x>w-3 || y>h-3) return;
pImg[(y-1)*w+x-2]=1;
pImg[ y *w+x-2]=1;
pImg[(y+1)*w+x-2]=1;
pImg[(y+2)*w+x-1]=1;
pImg[(y+2)*w+ x ]=1;
pImg[(y+2)*w+x+1]=1;
pImg[(y+1)*w+x+2]=1;
pImg[ y *w+x+2]=1;
pImg[(y-1)*w+x+2]=1;
pImg[(y-2)*w+x+1]=1;
pImg[(y-2)*w+ x ]=1;
pImg[(y-2)*w+x-1]=1;
}
画矩形函数,这个函数描绘了一个像素值为color的函数
void draw_rect(unsigned char *pImg, int x0, int y0, int x1, int y1, int w, int h, int color)
{
int i, j;
if(x0<0 || x1>w-1 || y0<0 || y1>h-1) return;
for(i=y0; i<y1; i++)
{
pImg[i*w+x0]=color;
pImg[i*w+x1]=color;
}
for(j=x0; j<x1; j++)
{
pImg[y0*w+j]=color;
pImg[y1*w+j]=color;
}
}
接下来是另外一个保存图像的函数,这里我们改变了调色板1,2,3,分别保留为红颜色,绿颜色,蓝颜色
void write_color_bmp(const char* pszFileName, unsigned char* pImg, int w, int h)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bmh;
RGBQUAD bmiColors[256];
FILE* fp;
int i;
fp=fopen(pszFileName, "wb");
if(fp==NULL) return;
//写位图文件头
bfh.bfType = 0x4d42;
bfh.bfSize = GET_ALIGN(w)*h+1078;
bfh.bfOffBits = 1078; bfh.bfReserved1=0;
bfh.bfReserved2 = 0;
//设置位图参数
bmh.biSize = 40;
bmh.biWidth = w;
bmh.biHeight = h;
bmh.biPlanes = 1;
bmh.biBitCount = 8;
bmh.biCompression = 0;
bmh.biSizeImage = GET_ALIGN(w)*h;
bmh.biXPelsPerMeter = 0;
bmh.biYPelsPerMeter = 0;
bmh.biClrUsed = 0;
bmh.biClrImportant = 0;
//创建256个灰度调色板
for(i=0; i<256; i++)
{
bmiColors[i].rgbRed = (BYTE)i;
bmiColors[i].rgbGreen = (BYTE)i;
bmiColors[i].rgbBlue = (BYTE)i;
}
//调色板1为红颜色
bmiColors[1].rgbRed = 255;
bmiColors[1].rgbGreen = 0;
bmiColors[1].rgbBlue = 0;
//调色板2为绿颜色
bmiColors[2].rgbRed = 0;
bmiColors[2].rgbGreen = 255;
bmiColors[2].rgbBlue = 0;
//调色板3为蓝颜色
bmiColors[3].rgbRed = 0;
bmiColors[3].rgbGreen = 0;
bmiColors[3].rgbBlue = 255;
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmh, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmiColors, sizeof(RGBQUAD), 256, fp); //行倒过来,对齐后写入
for(i=0; i<h; i++)
{
fwrite(pImg+(h-i-1)*w, 1, GET_ALIGN(w), fp);
}
fclose(fp);
}
接下来是我们的测试代码,注意我们要画颜色的时候最好要把保留的像素改变成近似的颜色。
比如我们这里保留了调色板1,2,3,在原先灰度图里,1,2,3其实和颜色0的纯黑色是非常接近的。
int step4(void)
{
int w, h, i;
unsigned char *pImg;
printf("step4: reserve color!/n");
pImg= read_bmp("test.bmp", &w, &h);
if(pImg==NULL) return -1;
//把原始像素值为1,2,3的全部设置为0
for(i=0; i<w*h; i++)
{
if(pImg[i]==1 || pImg[i]==2 || pImg[i]==3) pImg[i]=0;
}
paint_min(pImg, 98, 79, w, h);
paint_min(pImg, 49, 87, w, h);
draw_rect(pImg,10,10,110,110, w, h, 2);
draw_rect(pImg,174,156,194,176, w, h, 3);
write_color_bmp("test_color.bmp", pImg, w, h);
return 1;
}
这是输出的测试结果,可以看到我们画出了2个红色的小圈,一个绿色的大矩形框,一个蓝色的矩形框