📄 dibimage.cpp
字号:
}
// 计算灰度映射表
for (i = 0; i < 256; i++)
{
lTemp = 0;
for (j = 0; j <= i ; j++)
{
lTemp += lCount[j];
}
// 计算对应的新灰度值
bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth);
}
for(i = 0; i < lHeight; i++) // 每行
{
for(j = 0; j < lWidth; j++) // 每列
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值
*lpSrc = bMap[*lpSrc];
}
}
return TRUE;
}
/*************************************************************************************
*函数名称:
* NewDIB()
*
* 参数:
* width - 将要创建DIB的宽
* height - 将要创建DIB的高
* biBitCount - 将要创建DIB的位数。比如,如果要创建256色DIB,则此值为8
*
*返回值:
* HDIB - 成功返回DIB的句柄,否则返回NULL。
*
*说明:
* 该函数指定宽、高、颜色位数来创建一个新的DIB,并返回其句柄
*
*****************************************************************************************/
HDIB CDibImage::NewDIB(long width, long height, unsigned short biBitCount)
{
//计算新建的DIB每行所占的字节数
long dwindth = (width*biBitCount/8+3)/4*4;
//新建的DIB调色板中表项的数目
WORD color_num;
DWORD dwBitsSize;
//通过输入的biBitCount值来确定调色板的表项数目
switch(biBitCount)
{
//如果用1 bit来表示一个象素那么调色板中有两个表项
case 1:
color_num=2;
break;
//如果用4 bit来表示一个象素那么调色板中有16个表项
case 4:
color_num=16;
break;
//如果用8bit来表示一个象素,那么调色板中得表项有256中(本程序大多采用这种形式)
case 8:
color_num=256;
break;
//其他的情况调色扳中没有表项,即真彩位图
default:
color_num=0;
break;
}
//计算位图数据所占的空间
//dwindth *height为象素数据所占的空间
//40为位图信息头占的空间
//color_num*4为调色板的表项所占的空间(调色板每个表项占4各个字节)
dwBitsSize = dwindth *height + 40 + color_num*4;
//建立指向位图文件的指针
LPSTR pDIB;
//申请存储空间,并建立指向位图的句柄
HDIB hDIB=(HDIB) ::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, dwBitsSize);
//如果申请空间不成功返回错误信息
if (hDIB == 0)
{
return NULL;
}
//如果申请空间成功锁定内存,并将内存的指针传给pDIB
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
//建立指向位图信息头结构的指针
LPBITMAPINFO lpmf = (LPBITMAPINFO)pDIB;
//给位图信息头内的各个参量赋值
//指定位图信息头结构的大小为40字节
lpmf->bmiHeader.biSize = 40;
//指定新建位图的宽度
lpmf->bmiHeader.biWidth = width;
//指定新建位图的高度
lpmf->bmiHeader.biHeight = height;
//位平面数必须为1
lpmf->bmiHeader.biPlanes = 1;
//确定新建位图表示颜色是要用到的bit数
lpmf->bmiHeader.biBitCount = biBitCount;
//是否进行压缩
lpmf->bmiHeader.biCompression = 0;
//新建的位图中实际的位图数据所占的字节数
lpmf->bmiHeader.biSizeImage = dwindth *height;
//指定目标设备的水平分辨率
lpmf->bmiHeader.biXPelsPerMeter = 2925;
//指定目标设备的垂直分辨率
lpmf->bmiHeader.biYPelsPerMeter = 2925;
//新建图像实际用到的颜色数 如果为0则用到的颜色数为2的biBitCount次
lpmf->bmiHeader.biClrUsed = 0;
//指定新建图像中重要的颜色数,如果为0则所有的颜色都重要
lpmf->bmiHeader.biClrImportant= 0;
//如果新建的图像中含有调色板,则接下来对调色板的各种颜色分量赋初始值
if(color_num!=0)
{
for(int i=0;i<color_num;i++)
{
lpmf->bmiColors[i].rgbRed =(BYTE)i;
lpmf->bmiColors[i].rgbGreen =(BYTE)i;
lpmf->bmiColors[i].rgbBlue =(BYTE)i;
}
}
//解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
//返回新建位图的句柄
return hDIB;
}
void CDibImage::Convert256toGray(HDIB hDIB)
{
LPSTR lpDIB;
// 由DIB句柄得到DIB指针并锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);
LPSTR lpDIBBits; //指向DIB的象素的指针
LPSTR lpNewDIBBits; //指向DIB灰度图图像(新图像)开始处象素的指针
LONG lLineBytes;
unsigned char * lpSrc; //指向原图像象素点的指针
unsigned char * lpdest; //指向目标图像象素点的指针
unsigned char *ired,*igreen,*iblue;
long lWidth; //图像宽度和高度
long lHeight;
long i,j; //循环变量
lWidth = DIBWidth(lpDIB); //DIB 宽度
lHeight = DIBHeight(lpDIB); //DIB 高度
RGBQUAD *lpRGBquad;
lpRGBquad = (RGBQUAD *)&lpDIB[sizeof(BITMAPINFOHEADER)]; //INFOHEADER后为调色板
if(DIBNumColors(lpDIB) == 256) //256色位图不作任何处理
{
return ;
}
if(DIBNumColors(lpDIB) != 256) //非256色位图将它灰度化
{
lLineBytes = WIDTHBYTES(lWidth*8*3);
lpdest= new BYTE[lHeight*lWidth];
lpDIBBits = (LPSTR)lpDIB + sizeof(BITMAPINFOHEADER);//指向DIB象素
for(i = 0;i < lHeight; i++)
for(j = 0;j < lWidth*3; j+=3)
{
ired = (unsigned char*)lpDIBBits + lLineBytes * i + j + 2;
igreen = (unsigned char*)lpDIBBits + lLineBytes * i + j + 1;
iblue = (unsigned char*)lpDIBBits + lLineBytes * i + j ;
lpdest[i*lWidth + j/3] = (unsigned char)((*ired)*0.299 + (*igreen)*0.588 + (*iblue)*0.114);
}
//需要做三件事情:1、修改INFOHEADER 2、增加调色板 3、修改原图像灰度值
LPBITMAPINFOHEADER lpBI;
lpBI = (LPBITMAPINFOHEADER)lpDIB;
lpBI->biBitCount = 8;
//设置灰度调色板
for(i = 0;i < 256;i++)
{
lpRGBquad[i].rgbRed = (unsigned char)i;
lpRGBquad[i].rgbGreen = (unsigned char)i;
lpRGBquad[i].rgbBlue = (unsigned char)i;
lpRGBquad[i].rgbReserved = 0;
}
lpNewDIBBits= FindDIBBits(lpDIB); //找到DIB图像象素起始位置
lLineBytes=WIDTHBYTES(lWidth * 8);
//修改灰度值
for(i = 0;i < lHeight; i++)
for(j = 0;j < lWidth; j++)
{
lpSrc = (unsigned char*)lpNewDIBBits + lLineBytes * i+ j ;
*lpSrc=lpdest[i*lWidth+j];
}
delete lpdest;
}
::GlobalUnlock ((HGLOBAL)hDIB);
}
BOOL CDibImage::Bicolour(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
unsigned char* lpSrc; // 指向源图像的指针
// LONG lTemp; // 临时变量
LONG i; // 循环变量
LONG j;
// BYTE bMap[256]; // 灰度映射表
LONG lLineBytes; // 图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);// 计算图像每行的字节数
// 计算各个灰度值的计数
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
if(*lpSrc>220)*lpSrc=255;
else *lpSrc=0;
}
}
return TRUE;
}
BOOL CDibImage::DeleteScaterJudge(LPSTR lpDIBBits, WORD lLineBytes, LPBYTE lplab, int lWidth, int lHeight, int x, int y, CPoint lab[], int lianXuShu)
{
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//长度加一
m_lianXuShu++;
//设定访问标志
lplab[lWidth * y +x] = true;
//保存访问点坐标
lab[m_lianXuShu-1].x = x;
lab[m_lianXuShu-1].y = y;
//象素的灰度值
int gray;
//指向象素的指针
LPSTR lpSrc;
//长度判定
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//下面进入递归
else
{
//考察上下左右以及左上、右上、左下、右下八个方向
//如果是黑色点,则调用函数自身进行递归
//考察下面点
lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y-1 >=0 && gray == 0 && lplab[(y-1)*lWidth+x] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y-1,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//左下点
lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x-1;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y-1 >=0 && x-1 >=0 && gray== 0 && lplab[(y-1)*lWidth+x-1] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y-1,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//左边
lpSrc=(char*)lpDIBBits + lLineBytes * y + x-1;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(x-1 >=0 && gray== 0 && lplab[y*lWidth+x-1] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//左上
lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x-1;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y+1 <lHeight && x-1 >= 0 && gray == 0 && lplab[(y+1)*lWidth+x-1] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y+1,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//上面
lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y+1 < lHeight && gray == 0 && lplab[(y+1)*lWidth+x] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y+1,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//右上
lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x+1;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y+1 <lHeight && x+1 <lWidth && gray == 0 && lplab[(y+1)*lWidth+x+1] == false)
//进行递归处理
DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x+1,y+1,lab,lianXuShu);
//判断长度
//如果连续长度满足要求,说明不是离散点,返回
if(m_lianXuShu>=lianXuShu)
return TRUE;
//右边
lpSrc=(char*)lpDIBBits + lLineBytes * y + x+1;
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -