用c语言读取24位位图bmp文件
源代码:#include<windows.h>#include<stdio.h>#defineBMP_SIZE_OFFSET18#defineBMP_DATA_OFFSE...
源代码:
#include <windows.h>
#include <stdio.h>
#define BMP_SIZE_OFFSET 18
#define BMP_DATA_OFFSET 54
int main(void)
{
//定义操作位图的变量
int w; //图像宽度
int h; //图像高度
char *buf, *p; //图像数据
int r,g,b,pix; //像素颜色
int x,y,x0,y0; //平面坐标
FILE *fp; //文件指针
int i,j;
//定义窗口和绘图设备的变量
HWND wnd; //窗口句柄
HDC dc; //绘图设备环境句柄
if((fp=fopen("b_0.bmp","rb"))==NULL){
printf("文件未找到\n");
return-1;
}
fseek(fp,18L,SEEK_SET);
fread(&w,4,1,fp); //取图像宽度
fread(&h,4,1,fp); //取图像高度
buf=(char *)malloc(w*h*3);
fseek(fp,54L,SEEK_SET); //定位到数据处
fread(buf,1,w*h*3,fp); //读取像素数据
fclose(fp);
wnd=GetForegroundWindow(); //获取窗口句柄
dc=GetDC(wnd); //获取绘图设备
x0=40; y0=40;
p=buf;
for(j=0;j<h;j++){
for(i=0;i<w;i++){
b=*p++; g=*p++; r=*p++;
pix=RGB(r,g,b); //合成像素颜色值
//pix=(r&0xFF)<<16|(g&0xFF)<<8|b&0xFF; //与上一句邓加
SetPixel(dc,x0+i, y0+h-j, pix); //画像素点
}
}
free(buf);
getchar();
return 0;
}
经过测试此程序可以在vc6下正常运行;
不过出现了一个很诡异的事:
图片正常显示:
================================================================
图片非正常显示:
原图
经过程序读取后显示的(非正常):
以上图片已经过反复确定为24位bmp位图!
求解出现问题的原因!
谢谢! 展开
#include <windows.h>
#include <stdio.h>
#define BMP_SIZE_OFFSET 18
#define BMP_DATA_OFFSET 54
int main(void)
{
//定义操作位图的变量
int w; //图像宽度
int h; //图像高度
char *buf, *p; //图像数据
int r,g,b,pix; //像素颜色
int x,y,x0,y0; //平面坐标
FILE *fp; //文件指针
int i,j;
//定义窗口和绘图设备的变量
HWND wnd; //窗口句柄
HDC dc; //绘图设备环境句柄
if((fp=fopen("b_0.bmp","rb"))==NULL){
printf("文件未找到\n");
return-1;
}
fseek(fp,18L,SEEK_SET);
fread(&w,4,1,fp); //取图像宽度
fread(&h,4,1,fp); //取图像高度
buf=(char *)malloc(w*h*3);
fseek(fp,54L,SEEK_SET); //定位到数据处
fread(buf,1,w*h*3,fp); //读取像素数据
fclose(fp);
wnd=GetForegroundWindow(); //获取窗口句柄
dc=GetDC(wnd); //获取绘图设备
x0=40; y0=40;
p=buf;
for(j=0;j<h;j++){
for(i=0;i<w;i++){
b=*p++; g=*p++; r=*p++;
pix=RGB(r,g,b); //合成像素颜色值
//pix=(r&0xFF)<<16|(g&0xFF)<<8|b&0xFF; //与上一句邓加
SetPixel(dc,x0+i, y0+h-j, pix); //画像素点
}
}
free(buf);
getchar();
return 0;
}
经过测试此程序可以在vc6下正常运行;
不过出现了一个很诡异的事:
图片正常显示:
================================================================
图片非正常显示:
原图
经过程序读取后显示的(非正常):
以上图片已经过反复确定为24位bmp位图!
求解出现问题的原因!
谢谢! 展开
3个回答
展开全部
可以使用C语言标准函数库中的fopen、fseek、fclose等系列函数来打开bmp位图文件,以及进行相应的处理,下面是一个demo,仅供参考。以下代码在vc6.0中编译通过。
#include <stdio.h>
#include <stdlib.h>
#define BITMAPFILEHEADERLENGTH 14 // The bmp FileHeader length is 14
#define BM 19778 // The ASCII code for BM
/* Test the file is bmp file or not */
void bmpFileTest(FILE* fpbmp);
/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp);
/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp);
//get r,g,b data
void bmpDataPart(FILE* fpbmp);
// output data to corresponding txt file
void bmpoutput(FILE *fpout);
unsigned int OffSet = 0; // OffSet from Header part to Data Part
long width ; // The Width of the Data Part
long height ; // The Height of the Data Part
unsigned char r[2000][2000],output_r[2000][2000];
unsigned char g[2000][2000],output_g[2000][2000];
unsigned char b[2000][2000],output_b[2000][2000];
int main(int argc, char* argv[])
{
/* Open bmp file */
unsigned char *fp_temp;
FILE *fpbmp;
FILE *fpout;
fpbmp= fopen("1.bmp", "rb");
if (fpbmp == NULL)
{
printf("Open bmp failed!!!\n");
return 1;
}
fpout= fopen("out.bmp", "wb+");
if (fpout == NULL)
{
printf("Open out.bmp failed!!!\n");
return 1;
}
bmpFileTest(fpbmp); //Test the file is bmp file or not
bmpHeaderPartLength(fpbmp); //Get the length of Header Part
BmpWidthHeight(fpbmp); //Get the width and width of the Data Part
//
fseek(fpbmp, 0L, SEEK_SET);
fseek(fpout, 0L, SEEK_SET);
fp_temp=(unsigned char *)malloc(OffSet);
fread(fp_temp, 1, OffSet, fpbmp);
fwrite(fp_temp,1,OffSet,fpout);
bmpDataPart(fpbmp); //Reserve the data to file
/*
如果您想对图片进行处理,请您再这里插入处理函数!!!!!!!!!!!!!!!!!!
*/
bmpoutput(fpout);
fclose(fpbmp);
fclose(fpout);
return 0;
}
void bmpoutput(FILE* fpout)
{
int i, j=0;
int stride;
unsigned char* pixout=NULL;
stride=(24*width+31)/8;
stride=stride/4*4;
pixout=(unsigned char *)malloc(stride);
fseek(fpout, OffSet, SEEK_SET);
for(j=0;j<height;j++)
{
for(i=0;i<width;i++)
{
pixout[i*3+2]=output_r[height-1-j][i];
pixout[i*3+1]=output_g[height-1-j][i];
pixout[i*3] =output_b[height-1-j][i];
}
fwrite(pixout, 1, stride, fpout);
}
}
void bmpDataPart(FILE* fpbmp)
{
int i, j=0;
int stride;
unsigned char* pix=NULL;
FILE* fpr;
FILE* fpg;
FILE* fpb;
if((fpr=fopen("bmpr.txt","w+")) == NULL)
{
printf("Failed to construct file bmpr.txt.!!!");
exit(1);
}
if((fpg=fopen("bmpg.txt","w+")) == NULL)
{
printf("Failed to construct file bmpg.txt.!!!");
exit(1);
}
if((fpb=fopen("bmpb.txt","w+")) == NULL)
{
printf("Failed to construct file bmpb.txt.!!!");
exit(1);
}
fseek(fpbmp, OffSet, SEEK_SET);
stride=(24*width+31)/8;
stride=stride/4*4;
pix=(unsigned char *)malloc(stride);
for(j=0;j<height;j++)
{
fread(pix, 1, stride, fpbmp);
for(i=0;i<width;i++)
{
r[height-1-j][i] =pix[i*3+2];
g[height-1-j][i] =pix[i*3+1];
b[height-1-j][i] =pix[i*3];
output_r[height-1-j][i] =pix[i*3+2];
output_g[height-1-j][i] =pix[i*3+1];
output_b[height-1-j][i] =pix[i*3];
}
}
for(i =0; i < height; i++)
{
for(j = 0; j < width-1; j++)
{
fprintf(fpb,"%4d",b[i][j]);
fprintf(fpg,"%4d",g[i][j]);
fprintf(fpr,"%4d",r[i][j]);
}
fprintf(fpb,"%4d\n",b[i][j]);
fprintf(fpg,"%4d\n",g[i][j]);
fprintf(fpr,"%4d\n",r[i][j]);
}
fclose(fpr);
fclose(fpg);
fclose(fpb);
}
void bmpFileTest(FILE* fpbmp)
{
unsigned short bfType = 0;
fseek(fpbmp, 0L, SEEK_SET);//seek_set 起始位置
fread(&bfType, sizeof(char), 2, fpbmp);
if (BM != bfType)
{
printf("This file is not bmp file.!!!\n");
exit(1);
}
}
/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp)
{
fseek(fpbmp, 10L, SEEK_SET);
fread(&OffSet, sizeof(char), 4, fpbmp);
printf("The Header Part is of length %d.\n", OffSet);
}
/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp)
{
fseek(fpbmp, 18L, SEEK_SET);
fread(&width, sizeof(char), 4, fpbmp);
fseek(fpbmp, 22L, SEEK_SET);
fread(&height, sizeof(char), 4, fpbmp);
printf("The Width of the bmp file is %ld.\n", width);
printf("The Height of the bmp file is %ld.\n", height);
}
展开全部
如果横向的一行叫做一个“扫描线”的话
那么每条扫描线的第一个字节一定是对齐到4字节边界的
就比如,假设一条扫描线21个像素,那么一条扫描线就是21*3=63字节
实际上每条扫描线会占用64字节,因为下一条扫描线的第一个字节要对齐到4字节边界
(所谓对齐到边界,就是 除4余0)
注意:以上是凭印象说的。文件里保存和内存里保存是不是一样的不太确定……
最简单的解决方案,你要加载的BMP都确定宽是4的倍数就可以了
那么每条扫描线的第一个字节一定是对齐到4字节边界的
就比如,假设一条扫描线21个像素,那么一条扫描线就是21*3=63字节
实际上每条扫描线会占用64字节,因为下一条扫描线的第一个字节要对齐到4字节边界
(所谓对齐到边界,就是 除4余0)
注意:以上是凭印象说的。文件里保存和内存里保存是不是一样的不太确定……
最简单的解决方案,你要加载的BMP都确定宽是4的倍数就可以了
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
行像素错了一位,导致图像倾斜了。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询