📄 dibapi.cpp
字号:
// 更新dwBuffUsed
dwBuffUsed ++;
}
}
// 写入编码结果
file.WriteHuge((LPSTR)lpDst, dwBuffUsed);
// 释放内存
delete lpDst;
//**************************************************************************
// 写入调色板信息
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;
// 表明是否是Win3.0 DIB的标记
BOOL bWinStyleDIB;
// 开辟一片缓冲区以保存调色板
lpDst = new BYTE[769];
// 调色板起始字节
* lpDst = 0x0C;
// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi = (LPBITMAPINFO)lpDIB;
// 获取指向BITMAPCOREINFO结构的指针
lpbmc = (LPBITMAPCOREINFO)lpDIB;
// 判断是否是WIN3.0的DIB
bWinStyleDIB = IS_WIN30_DIB(lpDIB);
// 读取当前DIB调色板
for (i = 0; i < 256; i ++)
{
if (bWinStyleDIB)
{
// 读取DIB调色板红色分量
lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed;
// 读取DIB调色板绿色分量
lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen;
// 读取DIB调色板蓝色分量
lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue;
}
else
{
// 读取DIB调色板红色分量
lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed;
// 读取DIB调色板绿色分量
lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen;
// 读取DIB调色板蓝色分量
lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue;
}
}
// 写入调色板信息
file.Write((LPSTR)lpDst, 769);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* ReadPCX256()
*
* 参数:
* CFile& file - 要读取的文件
*
* 返回值:
* HDIB - 成功返回DIB的句柄,否则返回NULL。
*
* 说明:
* 该函数将读取指定的256色PCX文件。将读取的结果保存在一个未压缩
* 编码的DIB对象中。
*
*************************************************************************/
HDIB WINAPI ReadPCX256(CFile& file)
{
// PCX文件头
PCXHEADER pcxHdr;
// DIB大小(字节数)
DWORD dwDIBSize;
// DIB句柄
HDIB hDIB;
// DIB指针
LPSTR pDIB;
// 循环变量
LONG i;
LONG j;
// 重复像素计数
int iCount;
// DIB高度
WORD wHeight;
// DIB宽度
WORD wWidth;
// 图像每行的字节数
LONG lLineBytes;
// 中间变量
BYTE bChar;
// 指向源图像象素的指针
BYTE * lpSrc;
// 指向编码后图像数据的指针
BYTE * lpDst;
// 临时指针
BYTE * lpTemp;
// 尝试读取PCX文件头
if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER))
{
// 大小不对,返回NULL。
return NULL;
}
// 判断是否是256色PCX文件,检查第一个字节是否是0x0A,
if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1))
{
// 非256色PCX文件,返回NULL。
return NULL;
}
// 获取图像高度
wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1;
// 获取图像宽度
wWidth = pcxHdr.wRight - pcxHdr.wLeft + 1;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(wWidth * 8);
// 计算DIB长度(字节)
dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes;
// 为DIB分配内存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
if (hDIB == 0)
{
// 内存分配失败,返回NULL。
return NULL;
}
// 锁定
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBI;
// 赋值
lpBI = (LPBITMAPINFOHEADER) pDIB;
// 给lpBI成员赋值
lpBI->biSize = 40;
lpBI->biWidth = wWidth;
lpBI->biHeight = wHeight;
lpBI->biPlanes = 1;
lpBI->biBitCount = 8;
lpBI->biCompression = BI_RGB;
lpBI->biSizeImage = wHeight * lLineBytes;
lpBI->biXPelsPerMeter = pcxHdr.wXResolution;
lpBI->biYPelsPerMeter = pcxHdr.wYResolution;
lpBI->biClrUsed = 0;
lpBI->biClrImportant = 0;
// 分配内存以读取编码后的象素
lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769];
lpTemp = lpSrc;
// 读取编码后的象素
if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) !=
file.GetLength() - sizeof(PCXHEADER) - 769 )
{
// 大小不对。
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 计算DIB中像素位置
lpDst = (BYTE *) FindDIBBits(pDIB);
// 一行一行解码
for (j = 0; j <wHeight; j++)
{
i = 0;
while (i < wWidth)
{
// 读取一个字节
bChar = *lpTemp;
lpTemp++;
if ((bChar & 0xC0) == 0xC0)
{
// 行程
iCount = bChar & 0x3F;
// 读取下一个字节
bChar = *lpTemp;
lpTemp++;
// bChar重复iCount次保存
memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount);
// 已经读取像素的个数加iCount
i += iCount;
}
else
{
// 保存当前字节
lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar;
// 已经读取像素的个数加1
i += 1;
}
}
}
// 释放内存
delete lpSrc;
//*************************************************************
// 调色板
// 读调色板标志位
file.Read(&bChar, 1);
if (bChar != 0x0C)
{
// 出错
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 分配内存以读取编码后的象素
lpSrc = new BYTE[768];
// 计算DIB中调色板的位置
lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER);
// 读取调色板
if (file.Read(lpSrc, 768) != 768)
{
// 大小不对。
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 释放内存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 给调色板赋值
for (i = 0; i < 256; i++)
{
lpDst[i * 4] = lpSrc[i * 3 + 2];
lpDst[i * 4 + 1] = lpSrc[i * 3 + 1];
lpDst[i * 4 + 2] = lpSrc[i * 3];
lpDst[i * 4 + 3] = 0;
}
// 释放内存
delete lpSrc;
// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回DIB句柄
return hDIB;
}
/****************************************************************************
*
* FUNCTION: BytesPerLine
*
* PURPOSE: Calculates the number of bytes in one scan line.
*
* PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER
that begins the CF_DIB block
*
* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
*
\****************************************************************************/
DWORD BytesPerLine(LPBYTE lpDIB)
{
return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount);
}
DWORD BytesPerLine(HDIB hDIB)
{
LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB);
DWORD dw = BytesPerLine(lpDIB);
GlobalUnlock(hDIB);
return dw;
}
/*************************************************************************
*
* 函数名称:
* FFT()
*
* 参数:
* complex<double> * TD - 指向时域数组的指针
* complex<double> * FD - 指向频域数组的指针
* r -2的幂数,即迭代次数
*
* 返回值:
* 无。
*
* 说明:
* 该函数用来实现快速付立叶变换。
*
************************************************************************/
VOID WINAPI FFT(complex<double> * TD, complex<double> * FD, int r)
{
// 付立叶变换点数
LONG count;
// 循环变量
int i,j,k;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex<double> *W,*X1,*X2,*X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
W = new complex<double>[count / 2];
X1 = new complex<double>[count];
X2 = new complex<double>[count];
// 计算加权系数
for(i = 0; i < count / 2; i++)
{
angle = -i * PI * 2 / count;
W[i] = complex<double> (cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex<double>) * count);
// 采用蝶形算法进行快速付立叶变换
for(k = 0; k < r; k++)
{
for(j = 0; j < 1 << k; j++)
{
bfsize = 1 << (r-k);
for(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * W[i * (1<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for(j = 0; j < count; j++)
{
p = 0;
for(i = 0; i < r; i++)
{
if (j&(1<<i))
{
p+=1<<(r-i-1);
}
}
FD[j]=X1[p];
}
// 释放内存
delete W;
delete X1;
delete X2;
}
/*************************************************************************
*
* 函数名称:
* Fourier()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对图像进行付立叶变换。
*
************************************************************************/
BOOL WINAPI Fourier(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
unsigned char* lpSrc;
// 中间变量
double dTemp;
// 循环变量
LONG i;
LONG j;
// 进行付立叶变换的宽度和高度(2的整数次方)
LONG w;
LONG h;
int wp;
int hp;
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while(h * 2 <= lHeight)
{
h *= 2;
hp++;
}
// 分配内存
complex<double> *TD = new complex<double>[w * h];
complex<double> *FD = new complex<double>[w * h];
// 行
for(i = 0; i < h; i++)
{
// 列
for(j = 0; j < w; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 给时域赋值
TD[j + w * i] = complex<double>(*(lpSrc), 0);
}
}
for(i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);
}
// 保存变换结果
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
TD[i + h * j] = FD[j + w * i];
}
}
for(i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);
}
// 行
for(i = 0; i < h; i++)
{
// 列
for(j = 0; j < w; j++)
{
// 计算频谱
dTemp = sqrt(FD[j * h + i].real() * FD[j * h + i].real() +
FD[j * h + i].imag() * FD[j * h + i].imag()) / 100;
// 判断是否超过255
if (dTemp > 255)
{
// 对于超过的,直接设置为255
dTemp = 255;
}
// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个象素的指针
// 此处不直接取i和j,是为了将变换后的原点移到中心
//lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
lpSrc = (unsigned char*)lpDIBBits + lLineBytes *
(lHeight - 1 - (i<h/2 ? i+h/2 : i-h/2)) + (j<w/2 ? j+w/2 : j-w/2);
// 更新源图像
* (lpSrc) = (BYTE)(dTemp);
}
}
// 删除临时变量
delete TD;
delete FD;
// 返回
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -