📄 dib.cpp
字号:
//拷贝图象信息头到目标内存
memcpy(pTempInfo,m_pBMI,sizeof(BITMAPINFOHEADER));
pTempInfo->bmiHeader.biClrUsed=0;
pTempInfo->bmiHeader.biBitCount=8;
//保存原来的每行字节数目
LineBytesOld=m_LineBytes;
//计算保存新的每行字节数
m_LineBytes=(DWORD)WIDTHBYTES(m_biWidth*pTempInfo->bmiHeader.biBitCount);
//计算新的图象字节数
pTempInfo->bmiHeader.biSizeImage=(DWORD)m_LineBytes*m_biHeight;
//保存原来图象字节数
dataBytesOld=m_dataBytes;
//保存新的图象字节数
m_dataBytes=pTempInfo->bmiHeader.biSizeImage;
//初始化颜色表
for(i=0;i<m_NumColors;i++)
{
pTempInfo->bmiColors[i].rgbBlue=(BYTE)i;
pTempInfo->bmiColors[i].rgbGreen=(BYTE)i;
pTempInfo->bmiColors[i].rgbRed=(BYTE)i;
pTempInfo->bmiColors[i].rgbReserved=(BYTE)0;
}
// 申请临时空间
if(NULL == (pTempData=(BYTE*)new char[m_dataBytes]))
{
#ifdef _DEBUG
AfxMessageBox("申请内存错误");
#endif
}
for(y=0;y<m_biHeight;y++)
{
lpPtr=m_pDIBData+(dataBytesOld-LineBytesOld-y*LineBytesOld);
lpTempData=pTempData+(m_dataBytes-m_LineBytes-y*m_LineBytes);
for(x=0;x<m_biWidth;x++)
{
Blue=(unsigned char)(*lpPtr++);
Green=(unsigned char)(*lpPtr++);
Red=(unsigned char)(*lpPtr++);
Y=(float)(Red*0.299+Green*0.587+Blue*0.114);
Gray=(BYTE)Y;
*(lpTempData++)=(unsigned char)Gray;
}
}
if(m_pBMI!=NULL)
{
delete m_pBMI;
m_pBMI=(BITMAPINFO*)new
char[sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD)];
}
if(m_pDIBData!=NULL)
{
delete m_pDIBData;
m_pDIBData=(BYTE*)new char[m_dataBytes];
}
memcpy(m_pDIBData,pTempData,m_dataBytes);
memcpy(m_pBMI,pTempInfo,sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD));
delete pTempData;
delete pTempInfo;
m_pBMF->bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPFILEHEADER)+m_NumColors*sizeof(RGBQUAD)+m_dataBytes);
m_pBMF->bfOffBits=(DWORD)(sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPFILEHEADER)+m_NumColors*sizeof(RGBQUAD));
}
/* else 如果是灰度图了
{
for(i=0;i<m_NumColors;i++)
{
Blue=(unsigned char)m_pBMI->bmiColors[i].rgbBlue;
Green=(unsigned char)m_pBMI->bmiColors[i].rgbGreen;
Red=(unsigned char)m_pBMI->bmiColors[i].rgbRed;
Y=(float)(Red*0.299+Green*0.587+Blue*0.114);
Gray=(BYTE)Y;
m_pBMI->bmiColors[i].rgbBlue=Gray;
m_pBMI->bmiColors[i].rgbGreen=Gray;
m_pBMI->bmiColors[i].rgbRed=Gray;
}
}*/
}
/*************************************************************************
*
* 函数名称:
* TemplateOperation()
*
* 参数:
* int TemplateType - 指定模板操作类型
* 返回值:
* void
*
* 说明:
* 该函数用于对图象进行模板运算。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
void CDIB::TemplateOperation(int TemplateType)
{
float coef;
int CoefArray[9];
BYTE*pTempData;
BYTE*lpTempData;
BYTE*lpPtr;
LONG x,y;
float TempNum;
switch(TemplateType)
{
case TEMPLATE_SMOOTH_BOX:
coef=(float)(1.0/9.0);
memcpy(CoefArray,Template_Smooth_Box,9*sizeof(int));
break;
case TEMPLATE_SMOOTH_GAUSS:
coef=(float)(1.0/16.0);
memcpy(CoefArray,Template_Smooth_Gauss,9*sizeof(int));
break;
case TEMPLATE_SHARPEN_LAPLACIAN:
coef=(float)1.0;
memcpy(CoefArray,Template_Sharpen_Laplacian,9*sizeof(int));
break;
}
pTempData=(BYTE*)new char[m_dataBytes];
memset(pTempData,255,m_dataBytes);
lpTempData=pTempData;
lpPtr=m_pDIBData;
memcpy(lpTempData,lpPtr,m_dataBytes);
for(y=1;y<m_biHeight-1;y++){
for(x=1;x<m_biWidth;x++){
lpPtr=m_pDIBData+(m_dataBytes-m_LineBytes-y*m_LineBytes)+x;
lpTempData=pTempData+(m_dataBytes-m_LineBytes-y*m_LineBytes)+x;
TempNum=(float)(*(lpPtr+m_LineBytes-1)*CoefArray[0]);
TempNum+=(float)(*(lpPtr+m_LineBytes)*CoefArray[1]);
TempNum+=(float)(*(lpPtr+m_LineBytes+1)*CoefArray[2]);
TempNum+=(float)(*(lpPtr-1)*CoefArray[3]);
TempNum+=(float)(*lpPtr*CoefArray[4]);
TempNum+=(float)(*(lpPtr+1)*CoefArray[5]);
TempNum+=(float)(*(lpPtr-m_LineBytes-1)*CoefArray[6]);
TempNum+=(float)(*(lpPtr-m_LineBytes)*CoefArray[7]);
TempNum+=(float)(*(lpPtr-m_LineBytes+1)*CoefArray[8]);
TempNum*=coef;
if(TempNum>255.0)*lpTempData=(BYTE)255;
else if(TempNum<0.0)
*lpTempData=(BYTE)fabs(TempNum);
else
*lpTempData=(BYTE)TempNum;
}
}
memcpy(m_pDIBData,pTempData,m_dataBytes);
delete pTempData;
}
/*************************************************************************
*
* 函数名称:
* AddNoise()
*
* 返回值:
* void
*
* 说明:
* 该函数用于对图像进行随机增加噪点
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
void CDIB::AddNoise()
{
// 指向源图像的指针
LPSTR lpSrc;
//循环变量
ULONG i;
ULONG j;
//生成伪随机种子
srand((unsigned)time(NULL));
//在图像中加噪
for (j = 0;j<m_biHeight;j++)
{
for(i = 0;i<m_LineBytes;i++)
{
if(rand()>31500)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)m_pDIBData + m_LineBytes * j + i;
//图像中当前点置为黑
*lpSrc = 0;
}
}
}
}
/*************************************************************************
*
* 函数名称:
* Conver8To4()
*
* 参数:
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行将位处理,将8位256色灰度图图将为16色灰度图
*
* 要求目标图像为8位256色灰度图。
************************************************************************/
BOOL CDIB::Convert8To4()
{
m_pBMF->bfType = 0x4d42;
BITMAPINFO* pTempInfo;
BYTE * lpPtr,* lpTempData, *pDibDataOld;
UINT dataBytesOld, LineBytesOld;
unsigned char Gray, newhalf1, newhalf2;
m_NumColors=16;
pTempInfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)+m_NumColors*sizeof(RGBQUAD)];
if(!pTempInfo)
{
return false;
}
//修改位深数字
(pTempInfo->bmiHeader).biBitCount = 4;
(pTempInfo->bmiHeader).biCompression = 0;// 无压缩
(pTempInfo->bmiHeader).biClrUsed = 0;
(pTempInfo->bmiHeader).biSize = sizeof(BITMAPINFOHEADER);
(pTempInfo->bmiHeader).biHeight = (m_pBMI->bmiHeader).biHeight;
(pTempInfo->bmiHeader).biWidth =(m_pBMI->bmiHeader).biWidth ;
(pTempInfo->bmiHeader).biPlanes = 1;
(pTempInfo->bmiHeader).biXPelsPerMeter = 0;
(pTempInfo->bmiHeader).biYPelsPerMeter = 0;
(pTempInfo->bmiHeader).biClrImportant = 16;
(pTempInfo->bmiHeader).biSizeImage = 0;
m_pBMF->bfOffBits = sizeof(BITMAPFILEHEADER)
+ sizeof(BITMAPINFOHEADER) + m_NumColors*sizeof(RGBQUAD);
m_pBMF->bfReserved1 = NULL;
m_pBMF->bfReserved2 = NULL;
//初始化颜色表
for(int i=0;i<m_NumColors;i++)
{
pTempInfo->bmiColors[i].rgbBlue=(BYTE)(i*16);
pTempInfo->bmiColors[i].rgbGreen=(BYTE)(i*16);
pTempInfo->bmiColors[i].rgbRed=(BYTE)(i*16);
pTempInfo->bmiColors[i].rgbReserved=(BYTE)0;
}
//修改新的图象文件字节数目
m_pBMF->bfSize -= (m_pBMF->bfSize - m_pBMF->bfOffBits)/2;
(pTempInfo->bmiHeader).biSizeImage = m_pBMF->bfSize - m_pBMF->bfOffBits;
//修改像数字节数
m_dataBytes /= 2;
LineBytesOld = m_LineBytes;
dataBytesOld = LineBytesOld * (m_pBMI->bmiHeader).biHeight;
m_LineBytes=(DWORD)WIDTHBYTES((m_pBMI->bmiHeader).biWidth * (pTempInfo->bmiHeader).biBitCount);
(pTempInfo->bmiHeader).biSizeImage = m_LineBytes * (pTempInfo->bmiHeader).biHeight;
BYTE * buf = (BYTE *) new char[m_dataBytes];
if(!buf)
{
//申请内存失败
return false;
}
pDibDataOld = m_pDIBData;
m_pDIBData = buf;
try
{
for(int y=0;y<m_biHeight;y++)
{
lpPtr=pDibDataOld+(dataBytesOld-LineBytesOld-y*LineBytesOld);
lpTempData=buf+(m_dataBytes - m_LineBytes - y*m_LineBytes);
for(int x=0;x<m_biWidth/2;x++)
{
Gray=(unsigned char)(*lpPtr++);
newhalf1 = (BYTE)(Gray / 16);
Gray=(unsigned char)(*lpPtr++);
newhalf2 = (BYTE)(Gray / 16);
newhalf1<<= 4;
newhalf1&= 0x00F0;
newhalf2&= 0x000F;
*(lpTempData++)=(unsigned char)(newhalf1 | newhalf2);
}
}
}
catch (...)
{
#ifdef _DEBUG
AfxMessageBox("catch exception");
#endif
return false;
}
if(pDibDataOld ) delete pDibDataOld;
if(m_pBMI) delete m_pBMI;
m_pBMI = pTempInfo;
return true;
}
/*************************************************************************
*
* 函数名称:
* GetInfoHeader()
*
* 参数:
* 返回值:
* BITMAPINFORHEADER* - 直接返回一个指向位图信息头的指针
*
* 说明:
* 该函数用于位图信息头的内存首地址.
*
* 注意如果CDIB对象未有效初始化时也可以调用本方法,但是返回的指针是无效的NULL
************************************************************************/
BITMAPINFOHEADER * CDIB::GetInfoHeader()
{
return (BITMAPINFOHEADER *)m_pBMI;
}
/*************************************************************************
*
* 函数名称:
* GetDibData()
*
* 参数:
* 返回值:
* BYTE * - 指向图片像数索引值数组的首地址。
*
* 说明:
* 该函数用于得到图象索引值数组的首地址。
*
* 注意:如果CDIB对象未有效初始化时也可以调用本方法,但是返回的是NULL
************************************************************************/
BYTE * CDIB::GetDibData()
{
return m_pDIBData;
}
/*************************************************************************
*
* 函数名称:
* Formate8()
*
* 参数:
* int middle - 指定划分黑白像点的分界值,即小于等于该值的像点将被划为黑色,反之则白色,默认值为250。
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行二值化。改变索引值值但不改变图象的调色板和位深.
*
* 要求输出图像为只有0和255两个索引值的灰度图像。
************************************************************************/
BOOL CDIB::Format8(int middle)
{
try
{
for(ULONG i = 0; i < this->m_biHeight; i++)
{
for(ULONG j = 0; j < this->m_biWidth; j++)
{
*(unsigned char *)(this->m_pDIBData + i*m_biWidth + j) < middle ? \
*(unsigned char *)(this->m_pDIBData + i*m_biWidth + j) = (unsigned char)0 :\
*(unsigned char *)(this->m_pDIBData + i*m_biWidth + j) = (unsigned char)255;
}
}
}
catch (...)
{
return FALSE;
}
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* CDIB()
*
* 参数:
* BITMAPFILEHEADER * fileHeader
* - 位图文件的文件头指针。
* BITMAPINFO * infoHeader
* - 位图文件信息指针。
* BYTE * dibBytes
* - 像数索引数组的首地址。
* 返回值:
*
*
* 说明:
* 该函数位类CDIB的有参构造函数,注意如果用此方法构造一个CDIB对象,务必保证在显式释放
* 任何一个参数指向的内存前调用对象的成员方法。也就是说通过本方法构造的 CDIB对象没有
* 复制构造函数的参数指向的内存,但是使用过后对象能释放本构造函数的参数指向的内存。
*
* 要求必须保证三个参数指向预期的内存空间.本函数不做参数无效检查。
************************************************************************/
CDIB::CDIB(BITMAPFILEHEADER *fileHeader, BITMAPINFO *infoHeader, BYTE* dibBytes)
{
m_pBMF = fileHeader;
m_pBMI = infoHeader;
m_pDIBData = dibBytes;
m_biWidth = infoHeader->bmiHeader.biWidth;
m_biHeight = infoHeader->bmiHeader.biHeight;
m_dwByteNumber = m_dataBytes = m_biWidth * m_biHeight;//每个像点占一个字节。
m_LineBytes = m_biWidth;
m_NumColors = infoHeader->bmiHeader.biClrUsed;
}
/*************************************************************************
*
* 函数名称:
* GetObjectWidth()
*
* 参数:
* int black - 指定划分物体存在的像数值,即若某列上有索引值不大于
* black的则认为该列有物体的像点存在。默认值是10
* 返回值:
* ULONG - 物体的像点总共分布在多少列上。
*
* 说明:
* 该函数用于对图像进行列扫描,得到总共有多少列上有黑色点,如果CIDB的重要数
* 据成员未初始化,则返回0。
*
* 要求目标图像为8位256色灰度图。
************************************************************************/
ULONG CDIB::GetObjectWidth(int black)
{
if(this->m_pDIBData == NULL || NULL == this->m_biHeight || NULL == this->m_biHeight)
{
return 0;
}
ULONG sum = 0;
BYTE * dibData = this->m_pDIBData;
for(ULONG j = 0; j < this->m_biWidth ; j++)
{
for(ULONG i = 0; i < this->m_biHeight; i++)
{
if( *(dibData + i*this->m_biWidth + j) <= black)//假如颜色索引小于10的为黑色
{
sum++;
break;//此列不用再扫描了。
}
}
}
return sum;
}
/*************************************************************************
*
* 函数名称:
* GetObjectHeight()
*
* 参数:
* int black - 指定划分物体存在的像数值,即若某列上有索引值不大于
* black的则认为该行有物体的像点存在。默认值是10
* 返回值:
* ULONG - 物体的像点总共分布在多少行上。
*
* 说明:
* 该函数用于对图像进行行扫描,得到总共有多少行上有黑色点,如果CIDB的重要数
* 据成员未初始化,则返回0。
*
* 要求目标图像为8位256色灰度图。
************************************************************************/
ULONG CDIB::GetObjectHeight(int black)
{
if(this->m_pDIBData == NULL || NULL == this->m_biHeight || NULL == this->m_biHeight)
{
return 0;
}
ULONG sum = 0;
BYTE * dibData = this->m_pDIBData;
for(ULONG i = 0; i < this->m_biHeight ; i++)
{
for(ULONG j = 0; j < this->m_biWidth; j++)
{
if( *(dibData + i*this->m_biWidth + j) <= black)//假如颜色索引小于10的为黑色
{
sum++;
break;//此行不用再扫描了。
}
}
}
return sum;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -