纯C语言读取一幅BMP图像,并对其进行水平镜像处理

一、基本信息 :

首先需要了解一幅BMP格式图像的存储格式,对于一幅BMP图像其储存格式如下:

(1)位图头:保存位图文件的总体信息。

(2)位图信息:保存位图图像的详细信息。

(3)调色板:保存所用颜色的定义。

(4)位图数据:保存一个又一个像素的实际图像。

详细的定义可参考:这篇文章:

https://blog.csdn.net/wsfdl/article/details/7957370

 

二、C语言实现一幅BMP图像读取,并对其进行水平镜像处理

#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include <math.h>
#include <Windows.h>


/*存储原图的像素宽度高度和位图深度*/
unsigned int Height = 0;
unsigned int Width = 0;
unsigned int bitCount = 0;


void BmpHeightLength(void)
{
	printf("The Image Height is of length %d.\n", Height);
}

void BmpWidthLength(void)
{
	printf("The Image Width is of length %d.\n", Width);
}

void BmpBitcountLength(void)
{
	printf("The Image BitCount is of length %d.\n", bitCount);
}


void main()
{

	/*打印本平台每个数据类型所占字节大小*/
	printf("unsigned char :  %d \n", sizeof(unsigned char));
	printf("unsigned int :  %d \n", sizeof(unsigned int));
	printf("unsigned short :  %d \n", sizeof(unsigned short));
	printf("unsigned long :  %d \n", sizeof(unsigned long));

	/**/
	/*header info*/
	unsigned char *fpBmpHeader;   //位图头
	unsigned char *fpFileHeader;  //位图信息

	/*BMP 调色板*/	
	RGBQUAD  *pColorTable;

	/*打开一幅BMP图像 ,并创建一幅 新BMP图*/
	FILE *fpbmp;
	FILE *fpout;

	fpbmp= fopen("1.bmp", "rb");
	
	if (fpbmp == NULL)
    {
		printf("Open bmp failed!!!\n");
    }
	else
	{
		printf("Open bmp success!!!\n");
	}	

	fpout = fopen("out.bmp", "wb+");
	if (fpout == NULL)
    {
		printf("Open out.bmp failed!!!\n");
    }
	else
	{
		printf("Open out.bmp success!!!\n");
	}

	//获取 位图信息 中的图像宽度 高度 和 位深度
	BITMAPFILEHEADER fileHead;
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fpbmp);

	BITMAPINFOHEADER infoHead;
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fpbmp);

	Width = infoHead.biWidth;
	Height = infoHead.biHeight;
	bitCount = infoHead.biBitCount;

	/*打印 获取的 BMP 位图信息*/

	BmpHeightLength();
	BmpWidthLength();
	BmpBitcountLength();

	/*复制原图中 位图头 信息到新图像*/
    fpFileHeader =   new unsigned char[(sizeof(BITMAPFILEHEADER ))];
	fseek(fpbmp, 0, SEEK_SET);  //定位原图 偏移位置
	fseek(fpout, 0, SEEK_SET);  //定位新图 偏移位置
	fread(fpFileHeader, 1, sizeof(BITMAPFILEHEADER ), fpbmp);
	fwrite(fpFileHeader,1,sizeof(BITMAPFILEHEADER ),fpout);


	/*复制原图中 位图 信息到新图像*/
    fpBmpHeader =   new unsigned char[(sizeof(BITMAPINFOHEADER ))];
	fseek(fpbmp, sizeof(BITMAPFILEHEADER) , SEEK_SET);
	fseek(fpout, sizeof(BITMAPFILEHEADER), SEEK_SET);
	fread(fpBmpHeader, 1, sizeof(BITMAPINFOHEADER ), fpbmp);
	fwrite(fpBmpHeader,1,sizeof(BITMAPINFOHEADER ),fpout);

	/*Copy 调色板 info*/
	pColorTable = new RGBQUAD[256];
	fseek(fpbmp, sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER ), SEEK_SET);
	fseek(fpout, sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER ), SEEK_SET);
	fread(pColorTable, sizeof(RGBQUAD), 256, fpbmp);
	fwrite(pColorTable,sizeof(RGBQUAD), 256, fpout);

	/*获取 bmp 像素数据*/
	unsigned char *pBmpBuf;
	int lineByte = (Width*bitCount / 8 + 3) / 4 * 4;  // 确保每行 像素个数为 4 的倍数
	pBmpBuf = new unsigned char[lineByte*Height];
	fseek(fpbmp, sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD), 
    SEEK_SET);
	fread(pBmpBuf, lineByte*Height, 1, fpbmp);
	fclose(fpbmp);


	/*图像处理*/
	unsigned char *pBmpBufOut;
	pBmpBufOut = new unsigned char[lineByte*Height];

	unsigned int i ,j =0;

	/*对图像进行水平镜像*/
	for(i = 0; i < Height ; i++)
	{
		for(j = 0; j < lineByte ; j += 4)
		{
			*(pBmpBufOut  + i*lineByte + j)= *( pBmpBuf + i*lineByte + (lineByte - j -1 - 3));
			*(pBmpBufOut  + i*lineByte + j + 1)= *( pBmpBuf + i*lineByte + (lineByte - j -1 - 2));
			*(pBmpBufOut  + i*lineByte + j + 2)= *( pBmpBuf + i*lineByte + (lineByte - j -1 - 1));
			*(pBmpBufOut  + i*lineByte + j + 3)= *( pBmpBuf + i*lineByte + (lineByte - j -1 - 0));

		}
	}
	fseek(fpout, sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD), SEEK_SET);
	fwrite(pBmpBufOut, lineByte*Height, sizeof(char), fpout);

	delete[] pBmpBufOut;
	delete[] pBmpBuf;
	fclose(fpout);

	/*
	size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
	
	(1)ptr:是一个指针,对fread来说,是要写入数据内容地址;
	(2)size:要读取内容的单字节数;
	(3)count:要进行写入size字节的数据项的个数;
	(4)stream:目标文件指针;
	*/

	/*
	int fseek(FILE *stream, long offset, int fromwhere);
	功能:把与fp有关的文件位置指针放到一个指定位置。
	格式:  int fseek(FILE *stream, long offset, int fromwhere);
	范例一:fseek(fp, 0L, SEEK_END);
	解释:文件指针定位到文件末尾,偏移0个字节
	范例二:  fseek(fp,50L,0);或fseek(fp,50L,SEEK_SET);
	解释:其作用是将位置指针移到离文件头50个字节处。
	*/

	/*
	size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);

	(1)buffer:是一个指针,对fwrite来说,是要获取数据的地址;
	(2)size:要写入内容的单字节数;
	(3)count:要进行写入size字节的数据项的个数;
	(4)stream:目标文件指针;
	*/

 
 
}

运行结果:

 

 

 

 

 

 

 

 

 

 

 

参考:https://blog.csdn.net/wsfdl/article/details/7957370

  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值