【图像处理基础】C语言对bmp图片进行处理

1.bmp文件的定义

#ifndef IMAGE_H
#define IMAGE_H
void image_info(FILE* file);
void image_save(FILE *file);
void image_gray();
void image_binarization();
void image_opposite();
void image_channel(); //抽取RGB通道
void image_bright();//改变图像亮度
typedef struct BMP
{
	//14字节
	unsigned short bfType; //文件标识 2字节 必须为BM
	unsigned int bfSize; //文件大小 4字节
	unsigned short bfReserved1; //保留,每字节以"00"填写 2字节
	unsigned short bfReserved2; //同上 2字节
	unsigned int bfOffBits; //记录图像数据区的起始位置(图象数据相对于文件头字节的偏移量)。 4字节
	//40字节
	unsigned int biSize; //表示本结构的大小 4字节
	int biWidth; //位图的宽度 4字节
	int biHeight; //位图的高度 4字节
	unsigned short biPlanes; //永远为1 , 2字节
	unsigned short biBitCount; //位图的位数 分为1 4 8 16 24 32 2字节
	unsigned int biCompression; //压缩说明 4字节
	unsigned int biSizeImage; //表示位图数据区域的大小以字节为单位 4字节
	int biXPelsPerMeter; //用象素/米表示的水平分辨率 4字节
	int biYPelsPerMeter; //用象素/米表示的垂直分辨率 4字节
	unsigned int biClrUsed; //位图使用的颜色索引数 4字节
	unsigned int biClrImportant; //对图象显示有重要影响的颜色索引的数目 4字节
} BMP;
int line_byte;
unsigned char *imagedata;
extern BMP bmp;
extern int line_byte;
extern unsigned char *imagedata;
#endif

2.bmp图片的读写以及保存处理

#include<stdio.h>
#include<stdlib.h>
#include"image.h"
void image_info(FILE *file)
{
	int times=3; //输入文件名次数。
	char bmp_name[10]; //文件名
	printf("\nplease enter a file name for reading:");
	do
	{
		if (times<3)
		{
			printf("\nplease enter a file name for reading again:");
		}
		fflush(stdin);
		gets(bmp_name);
		//printf("\n%s",bmp_name);
		file=fopen(bmp_name,"rb+"); //打开一个文件进行读写操作。
		--times;
		if (file==NULL)
		{
			printf("\nerror opening %s for reading! ",bmp_name);
		}
		else
		{
			break;
		}
	}
	while(times!=0);
	if (times==0)
	{
		printf("\nsorry, shutdown!");
		exit(1);
	}
	//读取图像信息
	fseek(file,0L,0); //读取图像文件类型
	fread(&bmp,sizeof(BMP),1,file);
	printf("\n bmp tpye: %u",bmp.bfType);
	printf("\n bmp size: %u",bmp.bfSize);
	printf("\n bmp reserved1: %u",bmp.bfReserved1);
	printf("\n bmp reserved2: %u",bmp.bfReserved2);
	printf("\n bmp offBits: %u",bmp.bfOffBits);
	printf("\n bmp bisize: %u",bmp.biSize);
	printf("\n bmp biWidth: %d",bmp.biWidth);
	printf("\n bmp biHeight: %d",bmp.biHeight);
	printf("\n bmp biplans: %u",bmp.biPlanes);
	printf("\n bmp biBitCount: %u",bmp.biBitCount);
	printf("\n bmp biCompression: %u",bmp.biCompression);
	printf("\n bmp biSizeImage: %u",bmp.biSizeImage);
	printf("\n bmp biXPelsPerMeter: %d",bmp.biXPelsPerMeter);
	printf("\n bmp biYPelsPerMeter: %d",bmp.biYPelsPerMeter);
	printf("\n bmp biClrUsed: %u",bmp.biClrUsed);
	printf("\n bmp biClrImportant: %u\n",bmp.biClrImportant);
	line_byte=(bmp.biWidth*bmp.biBitCount/8+3)/4*4; //获得图像数据每行的数据个数
	//printf("dfsa%u",bmp.line_byte);
	//bmp.imagedata=NULL;
	imagedata=(unsigned char*)malloc(bmp.biSizeImage);
	fseek(file,(long)bmp.bfOffBits,0);
	fread(imagedata,sizeof(unsigned char),bmp.biSizeImage,file);
	fclose(file);
}
//保存图像
void image_save(FILE *file)
{
	int times=3; //输入文件名次数。
	char bmp_name[10]; //文件名
	//int i; //记录数据区个数
	printf("\nplease enter a file name for writeing:");
	do
	{
		if (times<3)
		{
			printf("\nplease enter a file name for writeing again:");
		}
		fflush(stdin);
		gets(bmp_name);
		printf("\n%s",bmp_name);
		file=fopen(bmp_name,"wb+"); //打开一个文件进行读写操作。
		--times;
		if (file==NULL)
		{
			printf("\nerror opening %s for writing",bmp_name);
		}
		else
		{
			break;
		}
	}
	while(times!=0);
	if (times==0)
	{
		printf("\nsorry, shutdown!");
		exit(1);
	}
	//写文件头
	printf("\n%s",bmp_name);
	fseek(file,0L,0); //图像文件类型
	fwrite(&(bmp.bfType),sizeof(short),1,file);
	printf("\n bmp tpye: %d",bmp.bfType);
	fseek(file,2L,0); //图像文件大小
	fwrite(&(bmp.bfSize),sizeof(int),1,file);
	printf("\n bmp size: %d",bmp.bfSize);
	fseek(file,6L,0); //图像文件保留字1
	fwrite(&(bmp.bfReserved1),sizeof(short),1,file);
	printf("\n bmp reserved1: %d",bmp.bfReserved1);
	fseek(file,8L,0); //图像文件保留字2
	fwrite(&(bmp.bfReserved2),sizeof(short),1,file);
	printf("\n bmp reserved2: %d",bmp.bfReserved2);
	fseek(file,10L,0);//数据区的偏移量
	fwrite(&(bmp.bfOffBits),sizeof(short),1,file);
	printf("\n bmp offBits: %d",bmp.bfOffBits);
	fseek(file,14L,0);//文件头结构大小
	fwrite(&(bmp.biSize),sizeof(int),1,file);
	printf("\n bmp bisize: %d",bmp.biSize);
	fseek(file,18L,0);//图像的宽度
	fwrite(&(bmp.biWidth),sizeof(int),1,file);
	printf("\n bmp biWidth: %d",bmp.biWidth);
	fseek(file,22L,0);//图像的高度
	fwrite(&(bmp.biHeight),sizeof(int),1,file);
	printf("\n bmp biHeight: %d",bmp.biHeight);
	fseek(file,24L,0);//图像的面数
	fwrite(&(bmp.biPlanes),sizeof(short),1,file);
	printf("\n bmp biplans: %d",bmp.biPlanes);
	fseek(file,28L,0);//图像一个像素的字节数
	fwrite(&(bmp.biBitCount),sizeof(short),1,file);
	printf("\n bmp biBitCount: %d",bmp.biBitCount);
	fseek(file,30L,0);//图像压缩信息
	fwrite(&(bmp.biCompression),sizeof(short),1,file);
	printf("\n bmp biCompression: %d",bmp.biCompression);
	fseek(file,34L,0);//图像数据区的大小
	fwrite(&(bmp.biSizeImage),sizeof(int),1,file);
	printf("\n bmp biSizeImage: %d",bmp.biSizeImage);
	fseek(file,38L,0);//水平分辨率
	fwrite(&(bmp.biXPelsPerMeter),sizeof(int),1,file);
	printf("\n bmp biXPelsPerMeter: %d",bmp.biXPelsPerMeter);
	fseek(file,42L,0);//垂直分辨率
	fwrite(&(bmp.biYPelsPerMeter),sizeof(int),1,file);
	printf("\n bmp biYPelsPerMeter: %d",bmp.biYPelsPerMeter);
	fseek(file,46L,0);//颜色索引数
	fwrite(&(bmp.biClrUsed),sizeof(int),1,file);
	printf("\n bmp biClrUsed: %d",bmp.biClrUsed);
	fseek(file,50L,0);//重要颜色索引数
	fwrite(&(bmp.biClrImportant),sizeof(int),1,file);
	printf("\n bmp biClrImportant: %d\n",bmp.biClrImportant);
	fseek(file,(long)(bmp.bfOffBits),0);
	fwrite(imagedata,sizeof(unsigned char),bmp.biSizeImage,file);
	fclose(file);
}

3.bmp图片像素的处理(灰度化、二值化、反相、抽取RGB通道以及改变图像亮度)

//pixProcess.c文件
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include"image.h"
//灰度化
void image_gray()
{
	int i,j;
	unsigned char tmp;
	for (i=0;i<bmp.biHeight;i++)
	{
		for (j=0;j<line_byte/3;j++)
		{
			tmp=0.11*(*(imagedata+i*line_byte+j*3+0))+0.59*(*(imagedata+i*line_byte+j*3+1))+0.3*(*(imagedata+i*line_byte+j*3+2));
			imagedata[i*line_byte+j*3+0]=tmp;
			imagedata[i*line_byte+j*3+1]=tmp;
			imagedata[i*line_byte+j*3+2]=tmp;
			//printf("\nnidsfh%d %d",i,j);
		}
	}
}
//二值化
void image_binarization()
{
	int i,j;
	for (i=0;i<bmp.biHeight;i++)
	{
		for (j=0;j<line_byte;j++)
		{
			if ((*(imagedata+i*line_byte+j))<128)
			{
				imagedata[i*line_byte+j]=0;
			}
			else
			{
				imagedata[i*line_byte+j]=255;
			}
		}
	}
}
//反相
void image_opposite() 
{
	int i,j;
	for (i=0;i<bmp.biHeight;i++)
	{
		for (j=0;j<line_byte;j++)
		{
			imagedata[i*line_byte+j]=abs(255-imagedata[i*line_byte+j]);
		}
	}
}
//抽取RGB通道
void image_channel() 
{
	int i,j;
	char rgb;
	printf("\nplease enter a char(r/g/b): ");
	fflush(stdin);
	scanf("%c",&rgb);
	if (rgb=='b')
	{
		for (i=0;i<bmp.biHeight;i++)
		{
			for (j=0;j<line_byte/3;j++)
			{
				imagedata[i*line_byte+3*j+1]=0;
				imagedata[i*line_byte+3*j+2]=0;
			}
		}
	}
	else if(rgb=='g')
	{
		for (i=0;i<bmp.biHeight;i++)
		{
			for (j=0;j<line_byte/3;j++)
			{
				imagedata[i*line_byte+3*j]=0;
				imagedata[i*line_byte+3*j+2]=0;
			}
		}
	}
	else
	{
		for (i=0;i<bmp.biHeight;i++)
		{
			for (j=0;j<line_byte/3;j++)
			{
				imagedata[i*line_byte+3*j]=0;
				imagedata[i*line_byte+3*j+1]=0;
			}
		}
	}
}
//改变图像亮度
void image_bright()
{
	int level;
	int i,j;
	printf("\n please enter the level of brightness[-255 to 255] :");
	fflush(stdin);
	scanf("%d",&level);
	for (i=0;i<bmp.biHeight;i++)
	{
		for (j=0;j<line_byte;j++)
		{
			if (level>=0)
			{
				if ((imagedata[i*line_byte+j]+level)>255)
					imagedata[i*line_byte+j]=255;
				else
					imagedata[i*line_byte+j]+=level;
			}
			else
			{
				if ((imagedata[i*line_byte+j]-abs(level))<0)
					imagedata[i*line_byte+j]=0;
				else
					imagedata[i*line_byte+j]+=level;
			}
		}
	}
}

4.

  • 7
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言中,处理BMP图片需要了解BMP文件的格式和结构。BMP文件由文件头、位图信息头和像素数据组成,其中文件头和位图信息头包含了BMP文件的基本信息,而像素数据则是BMP文件中真正存储图像信息的部分。 下面是一个简单的读取BMP文件的例子: ```c #include <stdio.h> #include <stdlib.h> #pragma pack(push, 1) // 确保按照1字节对齐 typedef struct { unsigned short bfType; // 文件类型 unsigned int bfSize; // 文件大小 unsigned short bfReserved1; // 保留字节 unsigned short bfReserved2; // 保留字节 unsigned int bfOffBits; // 像素数据偏移量 } BMPFileHeader; typedef struct { unsigned int biSize; // 信息头大小 int biWidth; // 图像宽度 int biHeight; // 图像高度 unsigned short biPlanes; // 颜色平面数 unsigned short biBitCount; // 每个像素的位数 unsigned int biCompression; // 压缩类型 unsigned int biSizeImage; // 像素数据大小 int biXPelsPerMeter; // 水平分辨率 int biYPelsPerMeter; // 垂直分辨率 unsigned int biClrUsed; // 使用的颜色数 unsigned int biClrImportant; // 重要颜色数 } BMPInfoHeader; #pragma pack(pop) int main() { FILE *fp = fopen("test.bmp", "rb"); if (fp == NULL) { printf("Failed to open file!\n"); return -1; } BMPFileHeader fileHeader; BMPInfoHeader infoHeader; fread(&fileHeader, sizeof(BMPFileHeader), 1, fp); fread(&infoHeader, sizeof(BMPInfoHeader), 1, fp); int width = infoHeader.biWidth; int height = infoHeader.biHeight; int bitCount = infoHeader.biBitCount; int lineByte = (width * bitCount + 31) / 32 * 4; // 每行像素所占字节数,4字节对齐 unsigned char *data = (unsigned char *)malloc(lineByte * height); fseek(fp, fileHeader.bfOffBits, SEEK_SET); fread(data, lineByte * height, 1, fp); fclose(fp); // 处理像素数据 // ... free(data); return 0; } ``` 在上面的例子中,我们首先定义了BMP文件头和位图信息头的结构体,并使用#pragma pack指令将结构体按照1字节对齐,确保结构体的大小和BMP文件中的格式一致。然后我们使用fopen函数打开BMP文件,并依次读取文件头和位图信息头,得到图像的宽度、高度、每个像素的位数等信息。接着根据图像的宽度、高度和每个像素的位数计算出每行像素所占的字节数,然后使用malloc函数动态分配内存,读取像素数据。最后我们可以对像素数据进行处理,如修改像素值、转换颜色空间等操作。 需要注意的是,在处理BMP文件时,如果像素数据的宽度不是4的倍数,则需要在每行像素数据后面添加一些填充字节,使得每行像素数据的总字节数是4的倍数。这样做是为了使像素数据在内存中的布局符合CPU的要求,提高读取速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Demo.demo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值