📄 dib.cpp
字号:
* 无
*
* \返回值:
* DWORD - 返回调色板的尺寸
*
* \说明:
* 该函数计算机调色板所需的尺寸
*
************************************************************************
*/
WORD CDib::PaletteSize()
{
// 临时变量
WORD NumColors;
LPBITMAPINFOHEADER lpbi=m_lpBMIH;
// 如果biClrUsed为零,且图象象素位数小于8,则计算调色板用到的表项数
NumColors = ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
? (int)(1 << (int)(lpbi)->biBitCount)\
: (int)(lpbi)->biClrUsed);
// 根据颜色表示的字节数计算调色板的尺寸
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
}
/*************************************************************************
*
* \函数名称:
* IsEmpty()
*
* \输入参数:
* 无
*
* \返回值:
* BOOL - 如果信息头和图象数据为空,则返回TRUE
*
* \说明:
* 判断信息头和图象数据是否为空
*
************************************************************************
*/
BOOL CDib::IsEmpty()
{
if( m_lpBMIH == NULL&&m_lpImage == NULL)
return TRUE;
else
return FALSE;
}
/*************************************************************************
*
* \函数名称:
* GetDibSaveDim()
*
* \输入参数:
* 无
*
* \返回值:
* CSize - DIB实际存储的高度和宽度
*
* \说明:
* 该函数函数用来得到dib的实际存储宽度(DWORD对齐)
*
************************************************************************
*/
CSize CDib::GetDibSaveDim()
{
CSize sizeSaveDim;
sizeSaveDim.cx = ( m_lpBMIH->biWidth * m_lpBMIH->biBitCount + 31)/32 * 4;
sizeSaveDim.cy = m_lpBMIH->biHeight;
return sizeSaveDim;
}
/*************************************************************************
*
* \函数名称:
* GetPixelOffset()
*
* \输入参数:
* int x - 象素在X轴的坐标
* int y - 象素在Y轴的坐标
*
* \返回值:
* int - 返回象素在图象数据块中的真实地址
*
* \说明:
* 该函数得到坐标为(x,y)的象素点的真实地址。由于DIB结构中对图象数据排列的
* 方式为从下到上,从左到右的,所以需要进行转换。
*
************************************************************************
*/
LONG CDib::GetPixelOffset(int x, int y)
{
CSize sizeSaveDim;
sizeSaveDim = GetDibSaveDim();
// LONG lOffset = (LONG) (sizeSaveDim.cy - y - 1) * sizeSaveDim.cx +
// x / (8 / m_lpBMIH->biBitCount);
LONG lOffset = (LONG) (sizeSaveDim.cy - y - 1) * sizeSaveDim.cx +
x * m_lpBMIH->biBitCount/8;
//如果m_lpBMIH->biBitCount>8,除数为零,会报错
return lOffset;
}
/*************************************************************************
*
* \函数名称:
* GetPixel()
*
* \输入参数:
* int x - 象素在X轴的坐标
* int y - 象素在Y轴的坐标
*
* \返回值:
* RGBQUAD - 返回DIB在该点真实的颜色
*
* \说明:
* 该函数得到DIB图象在该点真实的颜色。
* (函数有问题,已经修改了几个地方,别的还不清楚改动是否正确,需要验证)
************************************************************************
*/
RGBQUAD CDib::GetPixel(int x, int y)
{
// 颜色结构
RGBQUAD cColor;
// 根据每象素比特数得到此点的象素值
switch (m_lpBMIH->biBitCount)
{
case 1 :
//if (1<<(7-x%8) & *(LPBYTE)(m_lpImage+GetPixelOffset(x, y)))
if (1<<(7-x%8) & GetPixelOffset(x, y))
{
cColor.rgbBlue = 255;
cColor.rgbGreen = 255;
cColor.rgbRed = 255;
cColor.rgbReserved = 0;
}
else
{
cColor.rgbBlue = 0;
cColor.rgbGreen = 0;
cColor.rgbRed = 0;
cColor.rgbReserved = 0;
}
break;
case 4 :
{
//int nIndex = (*(LPBYTE)(m_lpImage+GetPixelOffset(x, y)) &
// (x%2 ? 0x0f : 0xf0)) >> (x%2 ? 0 : 4);
int nIndex = ((GetPixelOffset(x, y)) &
(x%2 ? 0x0f : 0xf0)) >> (x%2 ? 0 : 4);
LPRGBQUAD pDibQuad = (LPRGBQUAD) (m_lpvColorTable) + nIndex;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved = 0;
}
break;
case 8 :
{
//int nIndex = *(BYTE*)(m_lpImage+GetPixelOffset(x, y));//???
int nIndex = GetPixelOffset(x, y);
LPRGBQUAD pDibQuad = (LPRGBQUAD) (m_lpvColorTable) + m_lpImage[nIndex];//nIndex/3;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved = 0;
//针对8位的灰度图象,特例
//cColor.rgbRed=cColor.rgbGreen=cColor.rgbBlue=pDibQuad->rgbBlue;//m_lpImage[pDibQuad];
//cColor.rgbReserved = 0;
}
break;
default:
//int nIndex = *(BYTE*)(m_lpImage+GetPixelOffset(x, y));
int nIndex = GetPixelOffset(x,y);
cColor.rgbRed = m_lpImage[nIndex];
cColor.rgbGreen = m_lpImage[nIndex + 1];
cColor.rgbBlue = m_lpImage[nIndex + 2];
cColor.rgbReserved = 0;
break;
}
// 返回颜色结构
return cColor;
}
//---------------------------------------
// 图像缩放
// 0.25 <= zoom <= 4;
// 最后一条边界好像还没有做对 ?
//---------------------------------------
CDib* CDib::Resize(float zoom)
{
if ( 0.25 > zoom || zoom > 4) {
AfxMessageBox("zoom out of bound", MB_OK);
return NULL;
}
CSize size = this->GetDimensions();
DWORD Wold = (DWORD)size.cx;
DWORD Hold = (DWORD)size.cy;
DWORD Wnew = (DWORD)(size.cx * zoom);
DWORD Hnew = (DWORD)(size.cy * zoom);
CSize newSize;
newSize.cx = Wnew;
newSize.cy = Hnew;
CDib* newIm = new CDib(newSize, 24);
newIm->ComputeMetrics();
newIm->m_lpImage = (LPBYTE) new char[newIm->m_dwSizeImage];
LPBYTE lpold = this->m_lpImage;
LPBYTE lpnew = newIm->m_lpImage;
int lenold = this->GetDibSaveDim().cx;
int lennew = newIm->GetDibSaveDim().cx;
DWORD h0, w0, h1, w1;
float h01, w01;
float zoom_1 = 1/zoom;
for(DWORD h=0; h<Hnew; h++)
for(DWORD w=0; w<Wnew; w++)
{
// bilinear interpolation
h01 = (h*zoom_1);
h0 = (DWORD)h01;
h1 = h0 + 1;
w01 = (w*zoom_1);
w0 = (DWORD)w01;
w1 = w0 + 1;
float ratio_w = w01-w0;
float ratio_h = h01-h0;
if( (w0>=0) && (w1<Wold) && (h0>=0) && (h1<Hold) )
{
*(lpnew + lennew*h + w*3+2) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3+2)*(1-ratio_w)
+ *(lpold + lenold*h0 + w1*3+2)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*h1 + w0*3+2)*(1-ratio_w)
+ *(lpold + lenold*h1 + w1*3+2)*(ratio_w)) );
*(lpnew + lennew*h + w*3+1) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3+1)*(1-ratio_w)
+ *(lpold + lenold*h0 + w1*3+1)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*h1 + w0*3+1)*(1-ratio_w)
+ *(lpold + lenold*h1 + w1*3+1)*(ratio_w)) );
*(lpnew + lennew*h + w*3) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3)*(1-ratio_w)
+ *(lpold + lenold*h0 + w1*3)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*h1 + w0*3)*(1-ratio_w)
+ *(lpold + lenold*h1 + w1*3)*(ratio_w)) );
}
if( (w1 >= Wold) || (h1 >= Hold) )
{
*(lpnew + lennew*h + w*3+2) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3+2)*(1-ratio_w)
+ *(lpold + lenold*h0 + min(w1,Wold-1)*3+2)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*min(h1,Hold-1) + w0*3+2)*(1-ratio_w)
+ *(lpold + lenold*min(h1,Hold-1) + min(w1,Wold-1)*3+2)*(ratio_w)) );
*(lpnew + lennew*h + w*3+1) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3+1)*(1-ratio_w)
+ *(lpold + lenold*h0 + min(w1,Wold-1)*3+1)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*min(h1,Hold-1) + w0*3+1)*(1-ratio_w)
+ *(lpold + lenold*min(h1,Hold-1) + min(w1,Wold-1)*3+1)*(ratio_w)) );
*(lpnew + lennew*h + w*3) = (unsigned char)( (1-ratio_h) * (*(lpold + lenold*h0 + w0*3)*(1-ratio_w)
+ *(lpold + lenold*h0 + min(w1,Wold-1)*3)*(ratio_w))
+(ratio_h) * (*(lpold + lenold*min(h1,Hold-1) + w0*3)*(1-ratio_w)
+ *(lpold + lenold*min(h1,Hold-1) + min(w1,Wold-1)*3)*(ratio_w)) );
}
}
//
return newIm;
}
//
// 取直方图,mode 为方式,
// mode = 0 为 RGB 模式
// mode = 1 为 Gray 模式
// mode = 2 为 HSV 模式
//
// 暂时只支持 Gray 模式
//
float* CDib::GetHist(int mode)
{
if (mode!=1) return NULL;
CSize size;
size = GetDimensions();
int length = GetDibSaveDim().cx;
int* hist = new int[256];
for (int j=0; j<256; j++)
hist[j] = 0;
byte R,G,B,Gray;
for(j=0; j<size.cy; j++)
for( int i=0; i<size.cx; i++)
{
R=*(m_lpImage+length*(size.cy-1-j)+i*3+2);
G=*(m_lpImage+length*(size.cy-1-j)+i*3+1);
B=*(m_lpImage+length*(size.cy-1-j)+i*3);
Gray = unsigned char(0.11 * B + 0.59 * G + 0.30 * R);
hist[Gray] = hist[Gray] + 1;
}
float* reslt = new float[256];
for (j=0; j<256; j++)
reslt[j] = hist[j]/(float)(size.cx * size.cy);
return reslt;
}
//构造函数,根据源Dib得到新Dib
//用于开辟一块新的位图空间
CDib::CDib(CDib *pBMP)
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
// 根据象素位数计算调色板尺寸
ComputePaletteSize(pBMP->m_lpBMIH->biBitCount);
// 分配DIB信息头和调色板的内存
m_lpBMIH = (LPBITMAPINFOHEADER) new
char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries];
// 设置信息头内存分配状态
m_nBmihAlloc = crtAlloc;
// 设置信息头中的信息
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = pBMP->m_lpBMIH->biWidth;
m_lpBMIH->biHeight = pBMP->m_lpBMIH->biHeight;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = pBMP->m_lpBMIH->biBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = m_nColorTableEntries;
m_lpBMIH->biClrImportant= m_nColorTableEntries;
// 计算图象数据内存的大小,并设置此DIB的调色板的指针
ComputeMetrics();
// 将此DIB的调色板初始化为0
memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
if(pBMP->m_lpBMIH->biBitCount==8)
{
RGBQUAD * pPal;
pPal = (RGBQUAD *)m_lpvColorTable;
for (int i = 0; i < m_nColorTableEntries; i++)
{
pPal[i].rgbBlue =
pPal[i].rgbGreen =
pPal[i].rgbRed = i;
}
}
// 暂时不分配图象数据内存
m_lpImage = pBMP->m_lpImage;
}
BOOL CDib::ReadDIBFile(CString szFileName)
{
// 释放已经分配的内存
Empty();
// CFile *pFile = NULL;
// pFile=new CFile;
CFile *pFile=new CFile;
CFileException ex;
pFile->Open(szFileName,CFile::modeRead | CFile::shareDenyWrite,&ex);
// 临时存放信息的变量
int nCount, nSize;
BITMAPFILEHEADER bmfh;
// 进行读操作
try
{
// 读取文件头
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
// 如果文件类型部位"BM",则返回并进行相应错误处理
if(bmfh.bfType != 0x4d42)
{
char filename[256];
GetTempPath(256, filename);
strcat(filename, pFile->GetFileName());
FILE *tmp;
tmp = fopen(filename, "wb");
fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, tmp);
char buf[8192];
int len;
len = pFile->Read(buf, 8192);
while(len!=0)
{
fwrite(buf, len, 1, tmp);
len = pFile->Read(buf, 8192);
}
fclose(tmp);
}
else
{
// 计算信息头加上调色板的大小,并分配相应的内存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
// 读取信息头和调色板
nCount = pFile->Read(m_lpBMIH, nSize);
// 计算图象数据大小并设置调色板指针
ComputeMetrics();
// 计算调色板的表项数
ComputePaletteSize(m_lpBMIH->biBitCount);
// 如果DIB中存在调色板,则创建一个Windows调色板
MakePalette();
// 分配图象数据内存,并从文件中读取图象数据
m_lpImage = (LPBYTE)new char[m_dwSizeImage];
nCount = pFile->Read(m_lpImage, m_dwSizeImage);
}
}
// 错误处理
catch(CException* pe)
{
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
pSourceFile = pFile->Duplicate();
// 返回
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -