测试:
源24位位图: 无压缩, 高=20, 宽=108, 从中取出其中的左边宽18的部分(高度不变)下面的代码运行得到的位图,颜色不匹配(图像的大致轮廓是对的,但像右偏了一像素)
可能的问题:
1、代码中将源图的头和描述仅修改了一部分即作为目标图的头和描述,是否还有其他需要修改?
2、位图需要行字节为4的倍数,是否补齐、访问像素索引出了问题?
请帮忙测试一下,可以用画图软件随便弄一个108*20的24位图,代码拷贝过去即可运行(请将nDestWidth设为18,这样测试用例保持一致):void ConvertBitmap24(const char* pszSrcFName, const char* pszDestFName, long nDestWidth)
{
//= 从源24位位图提取指定的宽度(0~~nDestWidth),高度不变,生成目标24位位图文件
//= 假定输入一定为24位位图文件名, 且文件操作都正确 BITMAPFILEHEADER srcBMPFileHeader;
BITMAPINFO srcBMPInfo; FILE *fpBitmap = fopen(pszSrcFName, "rb"); //= 读取源位图头部: (位图标识: bmpFileHeader.bfType==0x4D42)
fread(&srcBMPFileHeader, sizeof(BITMAPFILEHEADER), 1, fpBitmap); //= 读取源位图描述 (24位位图解析: bmpInfo.bmiHeader.biBitCount == 24)
fread(&srcBMPInfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fpBitmap); //= 申请源位图数据缓冲
unsigned char* pbSrcBMPData = new unsigned char[srcBMPInfo.bmiHeader.biSizeImage]; //= 定位到源位图的数据部分
fseek(fpBitmap, srcBMPFileHeader.bfOffBits, 0);
//= 读取源位图的数据
fread(pbSrcBMPData, srcBMPInfo.bmiHeader.biSizeImage, 1, fpBitmap); //= 关闭源位图
fclose(fpBitmap); //= 源位图长宽(这里取绝对值, 不考虑颠倒的问题)
long nSrcWidth = abs(srcBMPInfo.bmiHeader.biWidth);
long nSrcHeight = abs(srcBMPInfo.bmiHeader.biHeight);
BITMAPFILEHEADER destBMPFileHeader;
BITMAPINFO destBMPInfo; //= 源位图的行字节数
int nSrcLineBytes = ( (nSrcWidth *24/32) + (((nSrcWidth *24)%32)?1:0) ) * 4; //= 目标位图的行字节数
int nDestLineBytes = ( (nDestWidth*24/32) + (((nDestWidth*24)%32)?1:0) ) * 4; //= 等同上面代码
//nSrcLineBytes = (nSrcWidth *24 + 31) / 32 * 4;
//nDestLineBytes = (nDestWidth*24 + 31) / 32 * 4; //= 将源位图头部的bfSize(文件大小)修改作为目标位图头部
memcpy(&destBMPFileHeader, &srcBMPFileHeader, sizeof(BITMAPFILEHEADER));
destBMPFileHeader.bfSize = srcBMPFileHeader.bfOffBits + nDestLineBytes*20; //= 将源位图描述的长宽、图像大小修改作为目标位图描述
memcpy(&destBMPInfo, &srcBMPInfo, sizeof(BITMAPINFO));
destBMPInfo.bmiHeader.biWidth = nDestWidth; // 指定宽度
destBMPInfo.bmiHeader.biHeight = nSrcHeight; // 高度不变
destBMPInfo.bmiHeader.biSizeImage = nSrcHeight * nDestLineBytes; //= 申请目标位图数据缓冲
unsigned char* pbDestBMPData = new unsigned char[destBMPInfo.bmiHeader.biSizeImage]; //= 预制全白色
memset(pbDestBMPData, 255, destBMPInfo.bmiHeader.biSizeImage); //= BGR三色
for (int nHeighLoop=0; nHeighLoop<nSrcHeight; nHeighLoop++)
{
for (int nWidthLoop=0; nWidthLoop<nDestWidth; nWidthLoop++)
{
//= 从源位图提取指定宽度的BGR
unsigned char b = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop ];
unsigned char g = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 1 ];
unsigned char r = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 2 ]; //= 设置目标位图BGR
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop ] = b;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 1 ] = g;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 2 ] = r;
}
} //= 释放源位图数据缓冲
delete pbSrcBMPData; //= 生成目标位图文件写入文件
fpBitmap = fopen(pszDestFName, "wb");
fwrite(&destBMPFileHeader, 1, sizeof(BITMAPFILEHEADER), fpBitmap);
fwrite(&destBMPInfo, 1, sizeof(BITMAPINFO), fpBitmap);
fwrite(pbDestBMPData, 1, destBMPInfo.bmiHeader.biSizeImage, fpBitmap);
fclose(fpBitmap); //= 释放目标位图数据缓冲
delete pbDestBMPData;
}
源24位位图: 无压缩, 高=20, 宽=108, 从中取出其中的左边宽18的部分(高度不变)下面的代码运行得到的位图,颜色不匹配(图像的大致轮廓是对的,但像右偏了一像素)
可能的问题:
1、代码中将源图的头和描述仅修改了一部分即作为目标图的头和描述,是否还有其他需要修改?
2、位图需要行字节为4的倍数,是否补齐、访问像素索引出了问题?
请帮忙测试一下,可以用画图软件随便弄一个108*20的24位图,代码拷贝过去即可运行(请将nDestWidth设为18,这样测试用例保持一致):void ConvertBitmap24(const char* pszSrcFName, const char* pszDestFName, long nDestWidth)
{
//= 从源24位位图提取指定的宽度(0~~nDestWidth),高度不变,生成目标24位位图文件
//= 假定输入一定为24位位图文件名, 且文件操作都正确 BITMAPFILEHEADER srcBMPFileHeader;
BITMAPINFO srcBMPInfo; FILE *fpBitmap = fopen(pszSrcFName, "rb"); //= 读取源位图头部: (位图标识: bmpFileHeader.bfType==0x4D42)
fread(&srcBMPFileHeader, sizeof(BITMAPFILEHEADER), 1, fpBitmap); //= 读取源位图描述 (24位位图解析: bmpInfo.bmiHeader.biBitCount == 24)
fread(&srcBMPInfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fpBitmap); //= 申请源位图数据缓冲
unsigned char* pbSrcBMPData = new unsigned char[srcBMPInfo.bmiHeader.biSizeImage]; //= 定位到源位图的数据部分
fseek(fpBitmap, srcBMPFileHeader.bfOffBits, 0);
//= 读取源位图的数据
fread(pbSrcBMPData, srcBMPInfo.bmiHeader.biSizeImage, 1, fpBitmap); //= 关闭源位图
fclose(fpBitmap); //= 源位图长宽(这里取绝对值, 不考虑颠倒的问题)
long nSrcWidth = abs(srcBMPInfo.bmiHeader.biWidth);
long nSrcHeight = abs(srcBMPInfo.bmiHeader.biHeight);
BITMAPFILEHEADER destBMPFileHeader;
BITMAPINFO destBMPInfo; //= 源位图的行字节数
int nSrcLineBytes = ( (nSrcWidth *24/32) + (((nSrcWidth *24)%32)?1:0) ) * 4; //= 目标位图的行字节数
int nDestLineBytes = ( (nDestWidth*24/32) + (((nDestWidth*24)%32)?1:0) ) * 4; //= 等同上面代码
//nSrcLineBytes = (nSrcWidth *24 + 31) / 32 * 4;
//nDestLineBytes = (nDestWidth*24 + 31) / 32 * 4; //= 将源位图头部的bfSize(文件大小)修改作为目标位图头部
memcpy(&destBMPFileHeader, &srcBMPFileHeader, sizeof(BITMAPFILEHEADER));
destBMPFileHeader.bfSize = srcBMPFileHeader.bfOffBits + nDestLineBytes*20; //= 将源位图描述的长宽、图像大小修改作为目标位图描述
memcpy(&destBMPInfo, &srcBMPInfo, sizeof(BITMAPINFO));
destBMPInfo.bmiHeader.biWidth = nDestWidth; // 指定宽度
destBMPInfo.bmiHeader.biHeight = nSrcHeight; // 高度不变
destBMPInfo.bmiHeader.biSizeImage = nSrcHeight * nDestLineBytes; //= 申请目标位图数据缓冲
unsigned char* pbDestBMPData = new unsigned char[destBMPInfo.bmiHeader.biSizeImage]; //= 预制全白色
memset(pbDestBMPData, 255, destBMPInfo.bmiHeader.biSizeImage); //= BGR三色
for (int nHeighLoop=0; nHeighLoop<nSrcHeight; nHeighLoop++)
{
for (int nWidthLoop=0; nWidthLoop<nDestWidth; nWidthLoop++)
{
//= 从源位图提取指定宽度的BGR
unsigned char b = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop ];
unsigned char g = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 1 ];
unsigned char r = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 2 ]; //= 设置目标位图BGR
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop ] = b;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 1 ] = g;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 2 ] = r;
}
} //= 释放源位图数据缓冲
delete pbSrcBMPData; //= 生成目标位图文件写入文件
fpBitmap = fopen(pszDestFName, "wb");
fwrite(&destBMPFileHeader, 1, sizeof(BITMAPFILEHEADER), fpBitmap);
fwrite(&destBMPInfo, 1, sizeof(BITMAPINFO), fpBitmap);
fwrite(pbDestBMPData, 1, destBMPInfo.bmiHeader.biSizeImage, fpBitmap);
fclose(fpBitmap); //= 释放目标位图数据缓冲
delete pbDestBMPData;
}
解决方案 »
- VS2008删除了系统菜单 怎么加回去
- 在添加新的菜单响应函数的时候,系统弹出无法添加/移除函数,因为父级类代码为只读
- 怎样写一个可以隐藏界面的c++程序,程序的功能是强行关机。
- CSocket如何设置连接超时? 急
- 有关CFileDialog的问题,诚恳指教!!
- 我是不是爱上陈慧琳了?今天上午看了<<东京攻略>>现在听着<<记事本>>总是想着她````````
- 请问2000下看过的flash存放在哪个目录?
- 金山游侠暂停游戏并弹出的原理
- mfc坐标转opengl坐标//dmodelivew找不到 在那个.h里呀..
- 这是我应聘的一道考题,你们看看难度如何,能解的出么?
- IOCP重用socket和更新CompletionKey
- 紧急要求资源,VC连SQL2000,数据备份问题
将BITMAPINFO中的RGBQUAD(颜色表)写入了文件,但是bfOffBits未增加该偏移,文件大小也未增加大小,导致数据整体偏移修改为:
//= 生成目标位图文件写入文件
fpBitmap = fopen(pszDestFName, "wb");
fwrite(&destBMPFileHeader, 1, sizeof(BITMAPFILEHEADER), fpBitmap);
fwrite(&destBMPInfo, 1, sizeof(BITMAPINFO), fpBitmap);
fseek(fpBitmap, destBMPFileHeader.bfOffBits, 0);
fwrite(pbDestBMPData, 1, destBMPInfo.bmiHeader.biSizeImage, fpBitmap);
fclose(fpBitmap);
{
//= 从源24位位图提取指定的宽度(0~~nDestWidth),高度不变,生成目标24位位图文件
//= 假定输入一定为24位位图文件名, 且文件操作都正确 BITMAPFILEHEADER srcBMPFileHeader;
BITMAPINFOHEADER srcBMPInfo; //该为BITMAPINFOHEADER FILE *fpBitmap = fopen(pszSrcFName, "rb"); //= 读取源位图头部: (位图标识: bmpFileHeader.bfType==0x4D42)
fread(&srcBMPFileHeader, sizeof(BITMAPFILEHEADER), 1, fpBitmap); //= 读取源位图描述 (24位位图解析: bmpInfo.bmiHeader.biBitCount == 24)
fread(&srcBMPInfo, sizeof(BITMAPINFOHEADER), 1, fpBitmap); //= 申请源位图数据缓冲
unsigned char* pbSrcBMPData = new unsigned char[srcBMPInfo.biSizeImage]; //= 定位到源位图的数据部分
fseek(fpBitmap, srcBMPFileHeader.bfOffBits, 0);
//= 读取源位图的数据
fread(pbSrcBMPData, srcBMPInfo.biSizeImage, 1, fpBitmap); //= 关闭源位图
fclose(fpBitmap); //= 源位图长宽(这里取绝对值, 不考虑颠倒的问题)
long nSrcWidth = abs(srcBMPInfo.biWidth);
long nSrcHeight = abs(srcBMPInfo.biHeight);
BITMAPFILEHEADER destBMPFileHeader;
BITMAPINFOHEADER destBMPInfo; //= 源位图的行字节数
int nSrcLineBytes = ( (nSrcWidth *24/32) + (((nSrcWidth *24)%32)?1:0) ) * 4; //= 目标位图的行字节数
int nDestLineBytes = ( (nDestWidth*24/32) + (((nDestWidth*24)%32)?1:0) ) * 4; //= 等同上面代码
//nSrcLineBytes = (nSrcWidth *24 + 31) / 32 * 4;
//nDestLineBytes = (nDestWidth*24 + 31) / 32 * 4; //= 将源位图头部的bfSize(文件大小)修改作为目标位图头部
memcpy(&destBMPFileHeader, &srcBMPFileHeader, sizeof(BITMAPFILEHEADER));
destBMPFileHeader.bfSize = srcBMPFileHeader.bfOffBits + nDestLineBytes*20; //= 将源位图描述的长宽、图像大小修改作为目标位图描述
memcpy(&destBMPInfo, &srcBMPInfo, sizeof(BITMAPINFOHEADER));
destBMPInfo.biWidth = nDestWidth; // 指定宽度
destBMPInfo.biHeight = nSrcHeight; // 高度不变
destBMPInfo.biSizeImage = nSrcHeight * nDestLineBytes; //= 申请目标位图数据缓冲
unsigned char* pbDestBMPData = new unsigned char[destBMPInfo.biSizeImage]; //= 预制全白色
memset(pbDestBMPData, 255, destBMPInfo.biSizeImage); //= BGR三色
for (int nHeighLoop=0; nHeighLoop <nSrcHeight; nHeighLoop++)
{
for (int nWidthLoop=0; nWidthLoop <nDestWidth; nWidthLoop++)
{
//= 从源位图提取指定宽度的BGR
unsigned char b = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop ];
unsigned char g = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 1 ];
unsigned char r = pbSrcBMPData [ nSrcLineBytes*nHeighLoop + 3*nWidthLoop + 2 ]; //= 设置目标位图BGR
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop ] = b;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 1 ] = g;
pbDestBMPData [ nDestLineBytes*nHeighLoop + 3*nWidthLoop + 2 ] = r;
}
} //= 释放源位图数据缓冲
delete pbSrcBMPData; //= 生成目标位图文件写入文件
fpBitmap = fopen(pszDestFName, "wb");
fwrite(&destBMPFileHeader, 1, sizeof(BITMAPFILEHEADER), fpBitmap);
fwrite(&destBMPInfo, 1, sizeof(BITMAPINFOHEADER), fpBitmap);
fwrite(pbDestBMPData, 1, destBMPInfo.biSizeImage, fpBitmap);
fclose(fpBitmap); //= 释放目标位图数据缓冲
delete pbDestBMPData;
}
---------------------
定义的时候直接定义为BITMAPINFOHEADER就可以了
这么处理也可以,这样就不会将BITMAPINFO中的RGBQUAD(颜色表)写入位图中,而只写入了等同BITMAPINFO的成员bmiHeader(BITMAPINFOHEADER)
不用fseek到偏移位置了