其他分享
首页 > 其他分享> > 图案法显示灰度图————利用Bayer表来对图像值进行二值显示

图案法显示灰度图————利用Bayer表来对图像值进行二值显示

作者:互联网

图案法是指灰度可以用一定比例的黑白点组成的区域表示,从而达到整体图像的灰度感。黑白点的位置选择成为图案化。

假设打印的时候,有一幅160*120*8bit的灰度图,需要用分辨率为200dpi*200dpi的激光打印机将其打印到128*9.6英寸的纸上。由于这张纸最多可以打(200*12.8)*(200*9.6)=2560*1920个点,所以每个像素可以用256个点大小的图案来表示灰度256.。而16*16的方块可以表示257个灰度级,所以灰度图像可以完全打印出来。

但是有个问题?就是图案构成的问题,即黑点打在哪里?例如,只有一个黑点的时候,我们可以打在中央,也可以打在边上。所以最后用来表示灰度的图案可以使规则的,也可以不是规则的。

现在假设用16*16个二值点来打印一个灰度像素,如果想存储256级灰度的图案的标准模板,就需要256*16*16的二值点阵,占用的空间比较大。一个更好的办法是:只存储一个16*16整数矩阵,成为标准图案,矩阵元素的取值为0~255.像素的实际灰度和阵列中的每一个值进行比较,当该值大于等于灰度时,标准图案中标号大于或等于灰度值额对应点打一黑点。

8*8的标准图案M3比较特殊,称为Bayer抖动表。但是如果用M3抖动表,每一个像素要用8*8的图案进行表示,一幅N*N的图将变成8N*8N大小。如果要在保持原图大小的情况下利用图案化技术,则只需要在所对应的图案中取一点,即重新采样。然后再用图案化技术,就能够保持原图大小。对于M3来说,即在原图中每8*8个点中取一点。但是实际上,这种方法并不可行,因为实际不知道这8*8个点中哪一点比较合适,而且8*8的间隔实在太大,生成的图像和原图肯定相差很大。

采用如下方法可以解决问题:

if((p[y][x]>>2) > bayer[y%8][x%8])

then 显示白点

else    显示黑点

p[y][x]代表该点灰度。在显示的时候首先将灰度右移两位,变成64级的,然后将x,y做模8运算,找到bayer表中的对应点,两者作比较,判断当前的像素输出为黑色还是白色。可以看到,模8运算使得原图分成了多个8*8的小块,每个小块和8*8的Bayer表相对应。小块中的每一个点都参与了比较,这样就避免了上面提到的划分过大的问题和选点的问题。
算法实现如下:

/*************************************************************************
 *
 * 函数名称:
 *   LimbPatternBayer()
 *
 * 参数:
 *   CDib  *pDib       - 指向CDib类的指针
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数利用BAYER表抖动显示图象。
 *
 ************************************************************************/


BOOL LimbPatternBayer(CDib *pDib)
{
	// Bayer表的定义
	BYTE BayerPattern[8][8]={ 0, 32,  8, 40,  2, 34, 10, 42,
							 48, 16, 56, 24, 50, 18, 58, 26,
							 12, 44,  4, 36, 14, 46,  6, 38,
							 60, 28, 52, 20, 62, 30, 54, 22,
							  3, 35, 11, 43,  1, 33,  9, 41,
							 51, 19, 59, 27, 49, 17, 57, 25,
							 15, 47,  7, 39, 13, 45,  5, 37,
							 63, 31, 55, 23, 61, 29, 53, 21};

	// 指向源图像的指针
	BYTE *	lpSrc;

	//图象的宽度和高度
	LONG    lWidth;
	LONG    lHeight;

	//得到实际的Dib图象存储大小
	CSize   SizeRealDim;
	SizeRealDim = pDib->GetDibSaveDim();

	// 图像每行的字节数
	LONG	lLineBytes;
	
	//得到图象的宽度和高度
	CSize   SizeDim;
	SizeDim = pDib->GetDimensions();
	lWidth  = SizeDim.cx;
	lHeight = SizeDim.cy;;

	// 计算图像每行的字节数
	lLineBytes = SizeRealDim.cx;
	
	//图像数据的指针
	LPBYTE  lpDIBBits = pDib->m_lpImage;

	// 循环变量
	int i, j;

	// 象素的值
	int nPixelValue;

	// 将图象二值化,利用BAYER表抖动显示图象
	for (j = 0; j < lHeight ; j++)
	{
		for(i = 0; i < lLineBytes ; i++)
		{
			// 指向源图像倒数第j行,第i个象素的指针			
			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;
			
			nPixelValue = (*lpSrc);

			nPixelValue =nPixelValue;
			
			// 右移两位后做比较
			if ( (nPixelValue>>2) > BayerPattern[j&7][i&7]) 
                //打白点    
				*(lpSrc)=(unsigned char)255; 
						
			else 
				//打黑点
				*(lpSrc)=(unsigned char)0; 
		}		
	}

	return true;
}

结果如下:

 

 

 

 

 

 

 

标签:原图,16,图象,图案,Bayer,图像,灰度,二值
来源: https://blog.51cto.com/u_15273495/2915294