不属于BitMap类如何进行
时间: 2024-02-09 09:08:40 浏览: 19
如果不使用 `Bitmap` 类,可以使用 Windows 提供的 GDI(图形设备接口)库来操作 BMP 图片。下面是一个简单的示例代码,演示了如何使用 GDI 库实现 BMP 图片的 RLE 压缩和解压缩:
```cpp
#include <windows.h>
// 压缩 BMP 图片
bool CompressBmp(LPCTSTR lpszSrcFile, LPCTSTR lpszDstFile)
{
// 打开 BMP 文件
HANDLE hFile = CreateFile(lpszSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return false;
}
// 读取 BMP 文件头
BITMAPFILEHEADER bmfHeader;
DWORD dwBytesRead;
if (!ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL) || dwBytesRead != sizeof(BITMAPFILEHEADER))
{
CloseHandle(hFile);
return false;
}
// 读取 BMP 位图信息头
BITMAPINFOHEADER bmiHeader;
if (!ReadFile(hFile, &bmiHeader, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL) || dwBytesRead != sizeof(BITMAPINFOHEADER))
{
CloseHandle(hFile);
return false;
}
// 计算行字节数
int nBytesPerLine = (bmiHeader.biWidth * bmiHeader.biBitCount + 7) / 8;
nBytesPerLine = (nBytesPerLine + 3) / 4 * 4;
// 计算压缩后的 BMP 数据区大小
DWORD dwCompressedSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (nBytesPerLine * bmiHeader.biHeight + bmiHeader.biHeight) / 2;
// 分配压缩后的 BMP 数据区
BYTE* pCompressedData = new BYTE[dwCompressedSize];
memset(pCompressedData, 0, dwCompressedSize);
// 填充压缩后的 BMP 文件头
BITMAPFILEHEADER bmfCompressedHeader;
bmfCompressedHeader.bfType = 0x4d42;
bmfCompressedHeader.bfSize = dwCompressedSize;
bmfCompressedHeader.bfReserved1 = 0;
bmfCompressedHeader.bfReserved2 = 0;
bmfCompressedHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 填充压缩后的 BMP 位图信息头
BITMAPINFOHEADER bmiCompressedHeader;
bmiCompressedHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiCompressedHeader.biWidth = bmiHeader.biWidth;
bmiCompressedHeader.biHeight = bmiHeader.biHeight;
bmiCompressedHeader.biPlanes = 1;
bmiCompressedHeader.biBitCount = bmiHeader.biBitCount;
bmiCompressedHeader.biCompression = BI_RLE4;
bmiCompressedHeader.biSizeImage = 0;
bmiCompressedHeader.biXPelsPerMeter = 0;
bmiCompressedHeader.biYPelsPerMeter = 0;
bmiCompressedHeader.biClrUsed = 0;
bmiCompressedHeader.biClrImportant = 0;
// 填充压缩后的 BMP 数据
memcpy(pCompressedData, &bmfCompressedHeader, sizeof(BITMAPFILEHEADER));
memcpy(pCompressedData + sizeof(BITMAPFILEHEADER), &bmiCompressedHeader, sizeof(BITMAPINFOHEADER));
BYTE* pCompressedLineData = pCompressedData + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BYTE* pLineData = new BYTE[nBytesPerLine];
for (int i = 0; i < bmiHeader.biHeight; i++)
{
// 读取一行 BMP 数据
if (!ReadFile(hFile, pLineData, nBytesPerLine, &dwBytesRead, NULL) || dwBytesRead != nBytesPerLine)
{
delete[] pLineData;
delete[] pCompressedData;
CloseHandle(hFile);
return false;
}
// 压缩一行 BMP 数据
int nCompressedLineSize = nBytesPerLine;
int nCompressedLineOffset = 0;
while (nCompressedLineOffset < nCompressedLineSize)
{
int nRunLength = 1;
BYTE bCode = 0x00;
// 计算重复值或非重复值的数量
while (nCompressedLineOffset + nRunLength < nCompressedLineSize && nRunLength <= 0x0f)
{
if (pLineData[nCompressedLineOffset + nRunLength] == pLineData[nCompressedLineOffset])
{
bCode = 0x00;
nRunLength++;
}
else
{
bCode = 0x01;
break;
}
}
// 写入非重复值的编码和数据
if (bCode == 0x01)
{
*pCompressedLineData++ = (BYTE)(nRunLength | 0x80);
for (int j = 0; j < nRunLength; j++)
{
*pCompressedLineData++ = pLineData[nCompressedLineOffset + j];
}
}
// 写入重复值的编码和数据
else
{
*pCompressedLineData++ = (BYTE)(nRunLength - 1);
*pCompressedLineData++ = pLineData[nCompressedLineOffset];
}
nCompressedLineOffset += nRunLength;
}
// 写入行结束标志
*pCompressedLineData++ = 0x00;
*pCompressedLineData++ = 0x00;
}
// 保存压缩后的 BMP 图片
DWORD dwBytesWritten;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
WriteFile(hFile, pCompressedData, dwCompressedSize, &dwBytesWritten, NULL);
CloseHandle(hFile);
delete[] pLineData;
delete[] pCompressedData;
return true;
}
// 解压缩 BMP 图片
bool DecompressBmp(LPCTSTR lpszSrcFile, LPCTSTR lpszDstFile)
{
// 打开 BMP 文件
HANDLE hFile = CreateFile(lpszSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return false;
}
// 读取 BMP 文件头
BITMAPFILEHEADER bmfHeader;
DWORD dwBytesRead;
if (!ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL) || dwBytesRead != sizeof(BITMAPFILEHEADER))
{
CloseHandle(hFile);
return false;
}
// 读取 BMP 位图信息头
BITMAPINFOHEADER bmiHeader;
if (!ReadFile(hFile, &bmiHeader, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL) || dwBytesRead != sizeof(BITMAPINFOHEADER))
{
CloseHandle(hFile);
return false;
}
// 计算行字节数
int nBytesPerLine = (bmiHeader.biWidth * bmiHeader.biBitCount + 7) / 8;
nBytesPerLine = (nBytesPerLine + 3) / 4 * 4;
// 计算解压缩后的 BMP 数据区大小
DWORD dwUncompressedSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nBytesPerLine * bmiHeader.biHeight;
// 分配解压缩后的 BMP 数据区
BYTE* pUncompressedData = new BYTE[dwUncompressedSize];
memset(pUncompressedData, 0, dwUncompressedSize);
// 填充解压缩后的 BMP 文件头
BITMAPFILEHEADER bmfUncompressedHeader;
bmfUncompressedHeader.bfType = 0x4d42;
bmfUncompressedHeader.bfSize = dwUncompressedSize;
bmfUncompressedHeader.bfReserved1 = 0;
bmfUncompressedHeader.bfReserved2 = 0;
bmfUncompressedHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 填充解压缩后的 BMP 位图信息头
BITMAPINFOHEADER bmiUncompressedHeader;
bmiUncompressedHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiUncompressedHeader.biWidth = bmiHeader.biWidth;
bmiUncompressedHeader.biHeight = bmiHeader.biHeight;
bmiUncompressedHeader.biPlanes