一、基本信息 :
首先需要了解一幅BMP格式图像的存储格式,对于一幅BMP图像其储存格式如下:
(1)位图头:保存位图文件的总体信息。
(2)位图信息:保存位图图像的详细信息。
(3)调色板:保存所用颜色的定义。
(4)位图数据:保存一个又一个像素的实际图像。
详细的定义可参考:这篇文章:
https://blog.csdn.net/wsfdl/article/details/7957370
二、C语言实现一幅BMP图像读取,并对其进行水平镜像处理
#include
#include
#include "stdafx.h"
#include
#include
/*存储原图的像素宽度高度和位图深度*/
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