zoukankan      html  css  js  c++  java
  • C/C++实现bmp文件读写

    • 之前知道点bmp图的格式,然后对8位操作过,然后今天弄了一下24位真彩色的。
    • C++读取、旋转和保存bmp图像文件编程实现
    • 主要是理解bmp文件的格式8/24位的区别
    • 8位图有调色板,24位在文件头和信息头之后就是图像数据区,但是保存24位图的时候,直接在文件头和信息头之后写图像数据,会有图像错位,查看bfOffBits=138 不等于54!

    BMP文件格式详解(BMP file format)

    • 实验输入图片

    实验一

    
    #include <stdio.h>  
    #include <stdlib.h>  
    
    typedef struct
    {
    	//unsigned short    bfType;  
    	unsigned long    bfSize;
    	unsigned short    bfReserved1;
    	unsigned short    bfReserved2;
    	unsigned long    bfOffBits;
    } ClBitMapFileHeader;
    
    typedef struct
    {
    	unsigned long  biSize;
    	long   biWidth;
    	long   biHeight;
    	unsigned short   biPlanes;
    	unsigned short   biBitCount;
    	unsigned long  biCompression;
    	unsigned long  biSizeImage;
    	long   biXPelsPerMeter;
    	long   biYPelsPerMeter;
    	unsigned long   biClrUsed;
    	unsigned long   biClrImportant;
    } ClBitMapInfoHeader;
    
    typedef struct
    {
    	unsigned char rgbBlue; //该颜色的蓝色分量  
    	unsigned char rgbGreen; //该颜色的绿色分量  
    	unsigned char rgbRed; //该颜色的红色分量  
    	unsigned char rgbReserved; //保留值  
    } ClRgbQuad;
    
    typedef struct
    {
    	int width;
    	int height;
    	int channels;
    	unsigned char* imageData;
    }ClImage;
    
    ClImage* clLoadImage(char* path);
    bool clSaveImage(char* path, ClImage* bmpImg);
    
    
    ClImage* clLoadImage(char* path)
    {
    	ClImage* bmpImg;
    	FILE* pFile;
    	unsigned short fileType;
    	ClBitMapFileHeader bmpFileHeader;
    	ClBitMapInfoHeader bmpInfoHeader;
    	int channels = 1;
    	int width = 0;
    	int height = 0;
    	int step = 0;
    	int offset = 0;
    	unsigned char pixVal;
    	ClRgbQuad* quad;
    	int i, j, k;
    
    	bmpImg = (ClImage*)malloc(sizeof(ClImage));
    	pFile = fopen(path, "rb");
    	if (!pFile)
    	{
    		free(bmpImg);
    		return NULL;
    	}
    
    	fread(&fileType, sizeof(unsigned short), 1, pFile); 
    	if (fileType == 0x4D42) //string "BM"
    	{
    		//printf("bmp file! 
    ");  
    
    		fread(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
    		/*printf("\\\\\\\\\\\\\\\\\\\\\\\n");
    		printf("bmp文件头信息:
    ");
    		printf("文件大小:%d 
    ", bmpFileHeader.bfSize);
    		printf("保留字:%d 
    ", bmpFileHeader.bfReserved1);
    		printf("保留字:%d 
    ", bmpFileHeader.bfReserved2);
    		printf("位图数据偏移字节数:%d 
    ", bmpFileHeader.bfOffBits);*/
    
    		fread(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
    		/*printf("\\\\\\\\\\\\\\\\\\\\\\\n");
    		printf("bmp文件信息头
    ");
    		printf("结构体长度:%d 
    ", bmpInfoHeader.biSize);
    		printf("位图宽度:%d 
    ", bmpInfoHeader.biWidth);
    		printf("位图高度:%d 
    ", bmpInfoHeader.biHeight);
    		printf("位图平面数:%d 
    ", bmpInfoHeader.biPlanes);
    		printf("颜色位数:%d 
    ", bmpInfoHeader.biBitCount);
    		printf("压缩方式:%d 
    ", bmpInfoHeader.biCompression);
    		printf("实际位图数据占用的字节数:%d 
    ", bmpInfoHeader.biSizeImage);
    		printf("X方向分辨率:%d 
    ", bmpInfoHeader.biXPelsPerMeter);
    		printf("Y方向分辨率:%d 
    ", bmpInfoHeader.biYPelsPerMeter);
    		printf("使用的颜色数:%d 
    ", bmpInfoHeader.biClrUsed);
    		printf("重要颜色数:%d 
    ", bmpInfoHeader.biClrImportant);
    		printf("\\\\\\\\\\\\\\\\\\\\\\\\n");*/
    
    		if (bmpInfoHeader.biBitCount == 8)
    		{
    			//printf("该文件有调色板,即该位图为非真彩色
    
    ");  
    			channels = 1;
    			width = bmpInfoHeader.biWidth;
    			height = bmpInfoHeader.biHeight;
    			offset = (channels*width) % 4;
    			if (offset != 0)
    			{
    				offset = 4 - offset;
    			}
    			//bmpImg->mat = kzCreateMat(height, width, 1, 0);  
    			bmpImg->width = width;
    			bmpImg->height = height;
    			bmpImg->channels = 1;
    			bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*height);
    			step = channels*width;
    
    			quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad) * 256);
    			fread(quad, sizeof(ClRgbQuad), 256, pFile);
    			free(quad);
    
    			for (i = 0; i<height; i++)
    			{
    				for (j = 0; j<width; j++)
    				{
    					fread(&pixVal, sizeof(unsigned char), 1, pFile);
    					bmpImg->imageData[(height - 1 - i)*step + j] = pixVal;   //每次一个像素处理
    				}
    				if (offset != 0)
    				{
    					for (j = 0; j<offset; j++)
    					{
    						fread(&pixVal, sizeof(unsigned char), 1, pFile);
    					}
    				}
    			}
    		}
    		else if (bmpInfoHeader.biBitCount == 24)
    		{
    			//printf("该位图为位真彩色
    
    ");  
    			channels = 3;
    			width = bmpInfoHeader.biWidth;
    			height = bmpInfoHeader.biHeight;
    
    			bmpImg->width = width;
    			bmpImg->height = height;
    			bmpImg->channels = 3;
    			bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width * 3 * height);
    			step = channels*width;
    
    			offset = (channels*width) % 4;
    			if (offset != 0)
    			{
    				offset = 4 - offset;
    			}
    
    			fseek(pFile, bmpFileHeader.bfOffBits - sizeof(bmpInfoHeader) - sizeof(bmpFileHeader), SEEK_CUR);  //138-54?感觉应该没有138才对啊
    
    			for (i = 0; i<height; i++)
    			{
    				for (j = 0; j<width; j++)
    				{
    					for (k = 0; k<3; k++)
    					{
    						fread(&pixVal, sizeof(unsigned char), 1, pFile);
    						bmpImg->imageData[(height - 1 - i)*step + j * 3 + k] = pixVal;  //
    					}
    					//kzSetMat(bmpImg->mat, height-1-i, j, kzScalar(pixVal[0], pixVal[1], pixVal[2]));  
    				}
    				if (offset != 0)
    				{
    					for (j = 0; j<offset; j++)
    					{
    						fread(&pixVal, sizeof(unsigned char), 1, pFile);
    					}
    				}
    			}
    		}
    	}
    
    	return bmpImg;
    }
    
    bool clSaveImage(char* path, ClImage* bmpImg)
    {
    	FILE *pFile;
    	unsigned short fileType;
    	ClBitMapFileHeader bmpFileHeader;
    	ClBitMapInfoHeader bmpInfoHeader;
    	int step;
    	int offset;
    	unsigned char pixVal = '';
    	int i, j;
    	ClRgbQuad* quad;
    
    	pFile = fopen(path, "wb");
    	if (!pFile)
    	{
    		return false;
    	}
    
    	fileType = 0x4D42;
    	fwrite(&fileType, sizeof(unsigned short), 1, pFile);
    
    	if (bmpImg->channels == 3)//24位,通道,彩图  
    	{
    		step = bmpImg->channels*bmpImg->width;
    		offset = step % 4;
    		if (offset != 4)
    		{
    			step += 4 - offset;
    		}
    
    		bmpFileHeader.bfSize = bmpImg->height*step + 54;
    		bmpFileHeader.bfReserved1 = 0;
    		bmpFileHeader.bfReserved2 = 0;
    		bmpFileHeader.bfOffBits = 54;
    		fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
    
    		bmpInfoHeader.biSize = 40;
    		bmpInfoHeader.biWidth = bmpImg->width;
    		bmpInfoHeader.biHeight = bmpImg->height;
    		bmpInfoHeader.biPlanes = 1;
    		bmpInfoHeader.biBitCount = 24;
    		bmpInfoHeader.biCompression = 0;
    		bmpInfoHeader.biSizeImage = bmpImg->height*step;
    		bmpInfoHeader.biXPelsPerMeter = 0;
    		bmpInfoHeader.biYPelsPerMeter = 0;
    		bmpInfoHeader.biClrUsed = 0;
    		bmpInfoHeader.biClrImportant = 0;
    		fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
    
    		for (i = bmpImg->height - 1; i>-1; i--)
    		{
    			for (j = 0; j<bmpImg->width; j++)
    			{
    				pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3];
    				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    				pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 1];
    				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    				pixVal = bmpImg->imageData[i*bmpImg->width * 3 + j * 3 + 2];
    				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    			}
    			if (offset != 0)
    			{
    				for (j = 0; j<offset; j++)
    				{
    					pixVal = 0;
    					fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    				}
    			}
    		}
    	}
    	else if (bmpImg->channels == 1)//8位,单通道,灰度图  
    	{
    		step = bmpImg->width;
    		offset = step % 4;
    		if (offset != 4)
    		{
    			step += 4 - offset;
    		}
    
    		bmpFileHeader.bfSize = 54 + 256 * 4 + bmpImg->width;
    		bmpFileHeader.bfReserved1 = 0;
    		bmpFileHeader.bfReserved2 = 0;
    		bmpFileHeader.bfOffBits = 54 + 256 * 4;
    		fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
    
    		bmpInfoHeader.biSize = 40;
    		bmpInfoHeader.biWidth = bmpImg->width;
    		bmpInfoHeader.biHeight = bmpImg->height;
    		bmpInfoHeader.biPlanes = 1;
    		bmpInfoHeader.biBitCount = 8;
    		bmpInfoHeader.biCompression = 0;
    		bmpInfoHeader.biSizeImage = bmpImg->height*step;
    		bmpInfoHeader.biXPelsPerMeter = 0;
    		bmpInfoHeader.biYPelsPerMeter = 0;
    		bmpInfoHeader.biClrUsed = 256;
    		bmpInfoHeader.biClrImportant = 256;
    		fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
    
    		quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad) * 256);
    		for (i = 0; i<256; i++)
    		{
    			quad[i].rgbBlue = i;
    			quad[i].rgbGreen = i;
    			quad[i].rgbRed = i;
    			quad[i].rgbReserved = 0;
    		}
    		fwrite(quad, sizeof(ClRgbQuad), 256, pFile);
    		free(quad);
    
    		for (i = bmpImg->height - 1; i>-1; i--)
    		{
    			for (j = 0; j<bmpImg->width; j++)
    			{
    				pixVal = bmpImg->imageData[i*bmpImg->width + j];
    				fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    			}
    			if (offset != 0)
    			{
    				for (j = 0; j<offset; j++)
    				{
    					pixVal = 0;
    					fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
    				}
    			}
    		}
    	}
    	fclose(pFile);
    
    	return true;
    }
     
    
    int main(int argc, char* argv[])
    {
    	ClImage* img = clLoadImage("F:\RANJIEWEN\CLQ_C_code\HOG_SVM_master\000001.bmp");
    	bool flag = clSaveImage("E:/result.bmp", img);
    	if (flag)
    	{
    		printf("save ok... 
    ");
    	}
    
    	while (1);
    	return 0;
    }
    
    • 在存24w位图的时候没有加fseek(pFile, bmpFileHeader.bfOffBits - sizeof(bmpInfoHeader) - sizeof(bmpFileHeader), SEEK_CUR); //138-54?感觉应该没有138才对啊存图不对,有错位

    实验二

    
    #include<iostream>
    #include <stdlib.h>
    #include <windows.h>
    #include <fstream>
    using namespace std;
    
    
    //---------------------------------------------------------------------------------------
    //以下该模块是完成BMP图像(彩色图像是24bit RGB各8bit)的像素获取,并存在文件名为xiang_su_zhi.txt中
    unsigned char *pBmpBuf;//读入图像数据的指针
    
    int bmpWidth;//图像的宽
    int bmpHeight;//图像的高
    RGBQUAD *pColorTable;//颜色表指针
    
    int biBitCount;//图像类型,每像素位数
    
    //-------------------------------------------------------------------------------------------
    //读图像的位图数据、宽、高、颜色表及每像素位数等数据进内存,存放在相应的全局变量中
    bool readBmp(char *bmpName)
    {
    	FILE *fp = fopen(bmpName, "rb");//二进制读方式打开指定的图像文件
    
    	if (fp == 0)
    		return 0;
    
    	//跳过位图文件头结构BITMAPFILEHEADER
    
    	fseek(fp, sizeof(BITMAPFILEHEADER), 0);
    
    	//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
    
    	BITMAPINFOHEADER head;
    
    	fread(&head, sizeof(BITMAPINFOHEADER), 1, fp); //获取图像宽、高、每像素所占位数等信息
    
    	bmpWidth = head.biWidth;
    
    	bmpHeight = head.biHeight;
    
    	biBitCount = head.biBitCount;//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
    
    	int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;//灰度图像有颜色表,且颜色表表项为256
    
    	if (biBitCount == 8)
    	{
    
    		//申请颜色表所需要的空间,读颜色表进内存
    
    		pColorTable = new RGBQUAD[256];
    
    		fread(pColorTable, sizeof(RGBQUAD), 256, fp);
    
    	}
    
    	//申请位图数据所需要的空间,读位图数据进内存
    
    	pBmpBuf = new unsigned char[lineByte * bmpHeight];
    
    	fread(pBmpBuf, 1, lineByte * bmpHeight, fp);
    
    	fclose(fp);//关闭文件
    
    	return 1;//读取文件成功
    }
    
    //-----------------------------------------------------------------------------------------
    //给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,将其写到指定文件中
    bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable)
    {
    
    	//如果位图数据指针为0,则没有数据传入,函数返回
    
    	if (!imgBuf)
    		return 0;
    
    	//颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
    
    	int colorTablesize = 0;
    
    	if (biBitCount == 8)
    		colorTablesize = 1024;
    
    	//待存储图像数据每行字节数为4的倍数
    
    	int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;
    
    	//以二进制写的方式打开文件
    
    	FILE *fp = fopen(bmpName, "wb");
    
    	if (fp == 0)
    		return 0;
    
    	//申请位图文件头结构变量,填写文件头信息
    
    	BITMAPFILEHEADER fileHead;
    
    	fileHead.bfType = 0x4D42;//bmp类型
    
    	//bfSize是图像文件4个组成部分之和
    
    	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte*height;
    
    	fileHead.bfReserved1 = 0;
    
    	fileHead.bfReserved2 = 0;
    
    	//bfOffBits是图像文件前3个部分所需空间之和
    
    	fileHead.bfOffBits = 54 + colorTablesize;
    
    	//写文件头进文件
    
    	fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
    
    	//申请位图信息头结构变量,填写信息头信息
    
    	BITMAPINFOHEADER head;
    
    	head.biBitCount = biBitCount;
    
    	head.biClrImportant = 0;
    
    	head.biClrUsed = 0;
    
    	head.biCompression = 0;
    
    	head.biHeight = height;
    
    	head.biPlanes = 1;
    
    	head.biSize = 40;
    
    	head.biSizeImage = lineByte*height;
    
    	head.biWidth = width;
    
    	head.biXPelsPerMeter = 0;
    
    	head.biYPelsPerMeter = 0;
    
    	//写位图信息头进内存
    
    	fwrite(&head, sizeof(BITMAPINFOHEADER), 1, fp);
    
    	//如果灰度图像,有颜色表,写入文件 
    
    	if (biBitCount == 8)
    		fwrite(pColorTable, sizeof(RGBQUAD), 256, fp);
    
    	//写位图数据进文件
    
    	fwrite(imgBuf, height*lineByte, 1, fp);
    
    	//关闭文件
    
    	fclose(fp);
    
    	return 1;
    
    }
    
    //----------------------------------------------------------------------------------------
    //以下为像素的读取函数
    void doIt()
    {
    
    	//读入指定BMP文件进内存
    
    	char readPath[] = "F:\RANJIEWEN\CLQ_C_code\HOG_SVM_master\000001.bmp";
    
    	readBmp(readPath);
    
    	//输出图像的信息
    
    	cout << "width=" << bmpWidth << " height=" << bmpHeight << " biBitCount=" << biBitCount << endl;
    
    	//循环变量,图像的坐标
    
    	//每行字节数
    
    	int lineByte = (bmpWidth*biBitCount / 8 + 3) / 4 * 4;
    
    	//循环变量,针对彩色图像,遍历每像素的三个分量
    
    	int m = 0, n = 0, count_xiang_su = 0;
    
    	//将图像左下角1/4部分置成黑色
    
    	ofstream outfile("图像像素.txt", ios::in | ios::trunc);
    
    	if (biBitCount == 8) //对于灰度图像
    	{
    		//------------------------------------------------------------------------------------
    		//以下完成图像的分割成8*8小单元,并把像素值存储到指定文本中。由于BMP图像的像素数据是从
    		//左下角:由左往右,由上往下逐行扫描的
    		int L1 = 0;
    		int hang = 63;
    		int lie = 0;
    		//int L2=0;
    		//int fen_ge=8;
    		for (int fen_ge_hang = 0; fen_ge_hang<8; fen_ge_hang++)//64*64矩阵行循环
    		{
    			for (int fen_ge_lie = 0; fen_ge_lie<8; fen_ge_lie++)//64*64列矩阵循环
    			{
    				//--------------------------------------------
    				for (L1 = hang; L1>hang - 8; L1--)//8*8矩阵行
    				{
    					for (int L2 = lie; L2<lie + 8; L2++)//8*8矩阵列
    					{
    						m = *(pBmpBuf + L1*lineByte + L2);
    						outfile << m << " ";
    						count_xiang_su++;
    						if (count_xiang_su % 8 == 0)//每8*8矩阵读入文本文件
    						{
    							outfile << endl;
    						}
    					}
    				}
    				//---------------------------------------------
    				hang = 63 - fen_ge_hang * 8;//64*64矩阵行变换
    				lie += 8;//64*64矩阵列变换
    				//该一行(64)由8个8*8矩阵的行组成
    			}
    			hang -= 8;//64*64矩阵的列变换
    			lie = 0;//64*64juzhen
    		}
    	}
    
    	//double xiang_su[2048];
    	//ofstream outfile("xiang_su_zhi.txt",ios::in|ios::trunc);
    	if (!outfile)
    	{
    		cout << "open error!" << endl;
    		exit(1);
    	}
    	else if (biBitCount == 24)
    	{//彩色图像
    		for (int i = 0; i<bmpHeight; i++)
    		{
    			for (int j = 0; j<bmpWidth; j++)
    			{
    				for (int k = 0; k<3; k++)//每像素RGB三个分量分别置0才变成黑色
    				{
    					//*(pBmpBuf+i*lineByte+j*3+k)-=40;
    					m = *(pBmpBuf + i*lineByte + j * 3 + k);
    					outfile << m << " ";
    					count_xiang_su++;
    					if (count_xiang_su % 8 == 0)
    					{
    						outfile << endl;
    					}
    					//n++;
    				}
    				n++;
    			}
    
    
    		}
    		cout << "总的像素个素为:" << n << endl;
    		cout << "----------------------------------------------------" << endl;
    	}
    
    	//将图像数据存盘
    
    	char writePath[] = "E://nvcpy.BMP";//图片处理后再存储
    
    	saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
    
    	//清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
    
    	delete[]pBmpBuf;
    
    	if (biBitCount == 8)
    		delete[]pColorTable;
    }
    
    void main()
    {
    	doIt();
    }
    
    • 没有fseek,24位图错位

    实验三

    • 我自己使用的8/24分别写成函数的
    
    #include "readbmp.h"
    #include "stdio.h"
    #include "string.h"
    #include "malloc.h"
    
    //typedef unsigned short WORD;
    //typedef unsigned int DWORD;
    //typedef int LONG;
    //typedef struct tagBITMAPFILEHEADER {
    //	WORD    bfType;
    //	DWORD   bfSize;
    //	WORD    bfReserved1;
    //	WORD    bfReserved2;
    //	DWORD   bfOffBits;
    //} BITMAPFILEHEADER;
    //typedef struct tagBITMAPINFOHEADER{
    //	DWORD      biSize;
    //	LONG        biWidth;
    //	LONG        biHeight;
    //	WORD       biPlanes;
    //	WORD       biBitCount;
    //	DWORD      biCompression;
    //	DWORD      biSizeImage;
    //	LONG        biXPelsPerMeter;
    //	LONG        biYPelsPerMeter;
    //	DWORD      biClrUsed;
    //	DWORD      biClrImportant;
    //} BITMAPINFOHEADER;
    
    
    #include "windows.h"  //BITMAPFILEHEADER包含文件
    
    myMat *loadBitmapFromFile24(const char *filePath, U8 **bits)     //24
    {
    	myMat *img;
    	img = (myMat*)malloc(sizeof(myMat));
    	if (!img) {
    		fprintf(stderr, "Unable to allocate memory
    ");
    		exit(1);
    	}
    
    	FILE *fp = fopen(filePath, "rb");
    	if (fp == NULL) {
    		exit(-1);
    	}
    	BITMAPFILEHEADER bfh;
    	if (fread(&bfh, sizeof(bfh), 1, fp) != 1) {
    		fclose(fp);
    		exit(-1);
    	}
    	BITMAPINFOHEADER bih;
    	if (fread(&bih, sizeof(bih), 1, fp) != 1) {
    		fclose(fp);
    		exit(-1);
    	}
    	if (bih.biBitCount != 24) {
    		fclose(fp);
    		printf("unsupported bitmap format.
    ");
    		exit(-1);
    	}
    	int imageSize = (bih.biWidth*3 + 3) / 4 * 4 * bih.biHeight;
    
    	img->width = bih.biWidth;
    	img->height = bih.biHeight;
    	img->type = myCV_8U;
    	img->dims = 2;
    	img->channels = 3;
    	img->step = imageSize / bih.biHeight;
    	img->totalsize = imageSize;
    	img->data = (uchar*)malloc(img->totalsize);
    	img->dataend = img->datalimit = (uchar*)img->data + img->totalsize;
    
    	fseek(fp, bfh.bfOffBits - sizeof(bfh) - sizeof(bih), SEEK_CUR);  //138-54?感觉应该没有138才对啊
    
    	if (fread(img->data, 1, imageSize, fp) != imageSize) {
    		fclose(fp);
    		exit(-1);
    	}
    	fclose(fp);
    
    	U8 *buffer = (U8 *)malloc(imageSize);
    	buffer = img->data;
    	*bits = buffer;
    
    	return img;
    }
    
    myMat *loadBitmapFromFile8(const char *filePath, U8 **bits)     //----8
    {
    	myMat *img;
    	img = (myMat*)malloc(sizeof(myMat));
    	if (!img) {
    		fprintf(stderr, "Unable to allocate memory
    ");
    		exit(1);
    	}
    
    	FILE *fp = fopen(filePath, "rb");
    	if (fp == NULL) {
    		exit(-1);
    	}
    	BITMAPFILEHEADER bfh;
    	if (fread(&bfh, sizeof(bfh), 1, fp) != 1) {
    		fclose(fp);
    		exit(-1);
    	}
    	BITMAPINFOHEADER bih;
    	if (fread(&bih, sizeof(bih), 1, fp) != 1) {
    		fclose(fp);
    		exit(-1);
    	}
    	if (bih.biBitCount != 8) {
    		fclose(fp);
    		printf("unsupported bitmap format.
    ");
    		exit(-1);
    	}
    	int imageSize = (bih.biWidth + 3) / 4 * 4 * bih.biHeight;
    
    	img->width = bih.biWidth;
    	img->height = bih.biHeight;
    	img->type = myCV_8U;
    	img->dims = 2;
    	img->channels = 1;
    	img->step = imageSize / bih.biHeight;
    	img->totalsize = imageSize ;
    	img->data = (uchar*)malloc(img->totalsize);
    	img->dataend = img->datalimit = (uchar*)img->data + img->totalsize;
    
    	fseek(fp, bfh.bfOffBits - sizeof(bfh) - sizeof(bih), SEEK_CUR);
    
    	U8 *buffer = (U8 *)malloc(imageSize );
    
    	if (fread(img->data, 1, imageSize, fp) != imageSize) {
    		fclose(fp);
    		exit(-1);
    	}
    	
    	fclose(fp);
    
    	*bits = buffer;
    
    	return img;
    }
    
    int CreateImage(IplImage_ *_img, int _width, int _height, U8 *_image_data)
    {
    	if (_img->valid)
    	{
    		return -1;	//这个图像结构体已经有用了
    	}
    	if (_width & 3)	//是否是4的整数倍
    	{
    		_img->width_step = (_width & (~3)) + 4;
    	}
    	else
    	{
    		_img->width_step = _width;
    	}
    	_img->width = _width;
    	_img->height = _height;
    	_img->image_data = _image_data;
    	_img->valid = 1;
    	return 0;
    }
    
    void ReleaseImage(IplImage_ *_img)
    {
    	_img->width_step = 0;
    	_img->width = 0;
    	_img->height = 0;
    	_img->image_data = 0;
    	_img->valid = 0;
    }
    
    void SaveGrayBitmap24(const char *fileName, const U8 *imageData, int width, int height)
    {
    	BITMAPFILEHEADER bfh;
    	BITMAPINFOHEADER bih;
    	DWORD palette[256];
    	int i, imageSize;
    	FILE *fp = fopen(fileName, "wb");
    	int widthS = (width*3 + 3) / 4 * 4;
    	imageSize = widthS* height;
    
    	if (fp == NULL)
    	{
    		return;
    	}
    
    	memset(&bfh, 0, sizeof(bfh));
    	bfh.bfType = 0x4d42;
    	bfh.bfSize = imageSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);;
    	bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
    	bfh.bfReserved1 = 0;
    	bfh.bfReserved2 = 0;
    	fwrite(&bfh, sizeof(bfh), 1, fp);
    
    	memset(&bih, 0, sizeof(bih));
    	bih.biSize = sizeof(bih);
    	bih.biWidth = width;
    	bih.biHeight = height;
    	bih.biPlanes = 1;
    	bih.biBitCount = 24;
    	bih.biCompression = 0;
    	bih.biSizeImage = imageSize;
    	bih.biXPelsPerMeter = 0;
    	bih.biYPelsPerMeter = 0;
    	bih.biClrUsed = 0;
    	bih.biClrImportant = 0;
    	fwrite(&bih, sizeof(bih), 1, fp);
    
    	for (i = 0; i < height; i++)
    	{
    		fwrite(imageData + (height - i - 1)*widthS, 1, widthS, fp);
    	}
    
    	fclose(fp);
    }
    
    void SaveGrayBitmap8(const char *fileName, const U8 *imageData, int width, int height)  //8
    {
    	BITMAPFILEHEADER bfh;
    	BITMAPINFOHEADER bih;
    	DWORD palette[256];
    	int i, imageSize;
    
    	FILE *fp = fopen(fileName, "wb");
    	int widthS = (width + 3) / 4 * 4;
    	imageSize = widthS* height;
    
    	if (fp == NULL)
    	{
    		return;
    	}
    
    	memset(&bfh, 0, sizeof(bfh));
    	bfh.bfType = 0x4d42;
    	bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * 4 + imageSize;
    	bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * 4;
    	bfh.bfReserved1 = 0;
    	bfh.bfReserved2 = 0;
    	fwrite(&bfh, sizeof(bfh), 1, fp);
    
    	memset(&bih, 0, sizeof(bih));
    	bih.biSize = sizeof(bih);
    	bih.biWidth = width;
    	bih.biHeight = height;
    	bih.biPlanes = 1;
    	bih.biBitCount = 8;
    	bih.biCompression = 0;
    	bih.biSizeImage = imageSize;
    	bih.biXPelsPerMeter = 0;
    	bih.biYPelsPerMeter = 0;
    	bih.biClrUsed = 0;
    	bih.biClrImportant = 0;
    	fwrite(&bih, sizeof(bih), 1, fp);
    
    	for (i = 0; i < 256; i++)
    	{
    		palette[i] = (i << 16) | (i << 8) | i;
    	}
    	fwrite(palette, sizeof(palette), 1, fp);
    
    	for (i = 0; i < height; i++)
    	{
    		fwrite(imageData + (height - i - 1)*widthS, 1, widthS, fp);
    	}
    
    	fclose(fp);
    }
    
    

    实验四

    • C++类实现
    void SaveToBmpGray::save(const unsigned char* src, int height, int width, std::string path, std::string name)
    {
    	int imagDataSize = height*width; // imag data size
    
    	//位图第三部分,调色板
    	RGBQUAD rgbQuad[256];
    	for (int i = 0; i < 256; ++i)
    	{
    		rgbQuad[i].rgbBlue = (BYTE)i;
    		rgbQuad[i].rgbGreen = (BYTE)i;
    		rgbQuad[i].rgbRed = (BYTE)i;
    		rgbQuad[i].rgbReserved = i;
    	}
    
    	//位图第一部分,位图文件头
    	BITMAPFILEHEADER *bfHeader{ new BITMAPFILEHEADER };
    	bfHeader->bfType = (WORD)0x4d42;  // string"BM"  
    	bfHeader->bfSize = (DWORD)(imagDataSize + sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(rgbQuad)); // file size
    	bfHeader->bfReserved1 = 0; // reserved  
    	bfHeader->bfReserved2 = 0; // reserved  
    	bfHeader->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(rgbQuad)); // real data 位置  
    
    	//位图第二部分,位图信息头  
    	BITMAPINFOHEADER *biHeader{ new BITMAPINFOHEADER };
    	biHeader->biSize = sizeof(BITMAPINFOHEADER);
    	biHeader->biWidth = width;
    	biHeader->biHeight = -height;//BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了  
    	biHeader->biPlanes = 1;//为1,不用改  
    	biHeader->biBitCount = 8; // 每个像素占用的bit
    	biHeader->biCompression = BI_RGB;//不压缩  
    	biHeader->biSizeImage = imagDataSize;
    	biHeader->biXPelsPerMeter = 0;//像素每米  
    	biHeader->biYPelsPerMeter = 0;
    	biHeader->biClrUsed = 0;//已用过的颜色,24位的为0  
    	biHeader->biClrImportant = 0;//每个像素都重要 
    
    	//打开文件并保存
    	//文件路径
    	std::string fpath;
    	fpath += path;
    	if (name.empty())
    		fpath += "IMG_";
    	else
    		fpath += name + "_";
    	SYSTEMTIME st;
    	GetLocalTime(&st);
    	char time[20];
    	sprintf_s(time, sizeof(st), "%4d%2d%2d_%2d%2d%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    	for (int i = 0; time[i]; ++i)
    	{
    		if (time[i] == ' ') time[i] = '0';
    	}
    	fpath += time;
    	fpath += ".bmp";
    	std::fstream file(fpath, std::ios::out | std::ios::binary);
    	file.write((char*)bfHeader, sizeof(BITMAPFILEHEADER));
    	file.write((char*)biHeader, sizeof(BITMAPINFOHEADER));
    	file.write((char*)rgbQuad, sizeof(rgbQuad));
    	file.write((char*)src, imagDataSize);
    	file.close();
    }
    
    void SaveToBmp24::save(const unsigned char* src, int height, int width, std::string path, std::string name)
    {
    	int imagDataSize = height*width * 3; // imag data size
    
    	//位图第一部分,位图文件头
    	BITMAPFILEHEADER *bfHeader{ new BITMAPFILEHEADER };
    	bfHeader->bfType = 0x4d42;  // string"BM"  
    	bfHeader->bfSize = imagDataSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // file size
    	bfHeader->bfReserved1 = 0; // reserved  
    	bfHeader->bfReserved2 = 0; // reserved  
    	bfHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); // real data 位置  
    
    	//位图第二部分,位图信息头  
    	BITMAPINFOHEADER *biHeader{ new BITMAPINFOHEADER };
    	biHeader->biSize = sizeof(BITMAPINFOHEADER);
    	biHeader->biWidth = width;
    	biHeader->biHeight = height;//BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了  
    	biHeader->biPlanes = 1;//为1,不用改  
    	biHeader->biBitCount = 24; // 每个像素占用的bit
    	biHeader->biCompression = BI_RGB;//不压缩  
    	biHeader->biSizeImage = imagDataSize;
    	biHeader->biXPelsPerMeter = 0;//像素每米  
    	biHeader->biYPelsPerMeter = 0;
    	biHeader->biClrUsed = 0;//已用过的颜色,24位的为0  
    	biHeader->biClrImportant = 0;//每个像素都重要 
    
    	//打开文件并保存
    	//文件路径
    	std::string fpath;
    	fpath += path;
    	if (name.empty())
    		fpath += "IMG_";
    	else
    		fpath += name + "_";
    	SYSTEMTIME st;
    	GetLocalTime(&st);
    	char time[20];
    	sprintf_s(time, sizeof(st), "%4d%2d%2d_%2d%2d%2d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    	for (int i = 0; time[i]; ++i)
    	{
    		if (time[i] == ' ') time[i] = '0';
    	}
    	fpath += time;
    	fpath += ".bmp";
    	std::fstream file(fpath, std::ios::out | std::ios::binary);
    	file.write((char*)bfHeader, sizeof(BITMAPFILEHEADER));
    	file.write((char*)biHeader, sizeof(BITMAPINFOHEADER));
    	file.write((char*)src, imagDataSize);
    	file.close();
    }
    
    
  • 相关阅读:
    jquery属性
    jquery选择器
    Django的模型
    win7安装RabbitMQ
    阿里云RDS备份的tar格式包恢复到本地自建数据库
    正确使用 Volatile 变量
    深入分析Volatile的实现原理
    volatile和synchronized的区别
    全面理解Java内存模型
    深入理解Feign之源码解析
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/6858636.html
Copyright © 2011-2022 走看看