2
回答
用C语言把24位bmp图像转换为24位bmp灰度图
终于搞明白,存储TCO原来是这样算的>>>   

我用C语言准备把一个24位bmp真彩图转换为24位bmp灰度图,根据rgb三色,把原来的rgb三个的值变为(rgb值相加求和再除以三)。但是结果一直不对,而且生成的图片很大。用来测试的原图只有2.13MB,后来的图片竟然有4G多。

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

typedef unsigned short WORD;                //Windwos 32位编译器  占2个字节
typedef unsigned char  BYTE;                //Windows 32位编译器  占1个字节
typedef unsigned long  DWORD;               //Windwos 32位编译器  占4个字节

//位图文件头
#pragma pack(1)                             //1字节对齐
typedef struct BITMAPFILEHEADER
{
	WORD  bfType;                           //位图文件标识符
	DWORD bfSize;                           //文件大小
	WORD  bfReserved1;                      //保留位
	WORD  bfReserved2;                      //保留位
	DWORD bfOffBits;                        //保存位图数据位置的地址偏移量,也就是起始地址
}BITMAPFILEHEADER;                          //结构体大小要和最大的对其
#pragma pack()


//位图信息头
#pragma pack(1)                             //1字节对齐
typedef struct BIMAPINFOHEADER
{
	DWORD  biSize;                          //说明BIMAPINFOHEADER结构所需要的字数
	DWORD  biWidth;                         //位图宽度(以像素个数表示)
	DWORD  biHeight;                        //位图高度(以像素个数表示)
	WORD   biPlanes;                        //保留所用色彩位面个数,不经常使用
	WORD   biBitCount;                      //保存每个像素的位数,它是图像颜色的深度
	DWORD  biCompression;                   //定义所用的压缩算法
	DWORD  biSizeImage;                     //保存原始位图数据的大小
	DWORD  biXPelsPeMeter;                  //保存图像水平方向分辨率
	DWORD  biYPelsPeMeter;                  //保存图像竖直方向分辨率
	DWORD  biClrUsed;                       //保存所用颜色数目
	DWORD  biClrImportant;                  //保存重要颜色数目,当每个颜色都重要时这个值与颜色数目相等
}BITMAPINFOHEADER;
#pragma pack()

//调色板
#pragma pack(1)
typedef struct RGBQUAD
{
	WORD  rgbBlue;                        //   蓝色的亮度(值范围为0-255)
	WORD  rgbGreen;                       //   绿色的亮度(值范围为0-255)
	WORD  rgbRed;                         //   红色的亮度(值范围为0-255)
	WORD  rgbReversed;                    //   保留,必须为0 
}RGBQUAD;
#pragma pack()


int main(void)
{
	FILE *in_bmp  = NULL;                   //指向源文件的文件指针
	FILE *out_bmp = NULL;                   //指向输出文件的文件指针

	BITMAPFILEHEADER *fhead  = NULL;        //文件头指针
	BITMAPINFOHEADER *fihead = NULL;        //信息头指针

	size_t is_ok;                           //接受返回值,用来判断文件读写是否成功

	fhead = (BITMAPFILEHEADER *)malloc(sizeof(BITMAPFILEHEADER));              //给文件头指针分配内存
	if (NULL == fhead)
	{
		printf("BITMAPFILEHEADER memory allocation failed\n");
	}

	fihead = (BITMAPINFOHEADER *)malloc(sizeof(BITMAPINFOHEADER));             //给信息头指针分配内存
	if (NULL == fihead)
	{
		printf("BITMAPINFOHEADER memory allocation failed\n");
	}

	in_bmp = fopen("C:\\Users\\Administrator\\Desktop\\3.bmp", "rb");          //打开源文件
	if (NULL == in_bmp)
	{
		printf("open file failed!\n");
	}

	out_bmp = fopen("C:\\Users\\Administrator\\Desktop\\test.bmp", "wb");      //打开修改过数据的文件,没有就创建
	if (NULL == out_bmp)
	{
		printf("open file failed!\n");
	}

	is_ok = fread(fhead, sizeof(BITMAPFILEHEADER), 1, in_bmp);                         //读取文件头
	if (0 == is_ok)
	{
		printf("read BITMAPFILEHEADER failed\n");
	}



	is_ok = fread(fihead, sizeof(BITMAPINFOHEADER), 1, in_bmp);                        //读取信息头
	if (0 == is_ok)
	{
		printf("read BITMAPINFOHEADER failed\n");
	}


	//写入头文件
	is_ok = fwrite(fhead, sizeof(BITMAPFILEHEADER), 1, out_bmp);
	if (0 == is_ok)
	{
		printf("write file failed!!\n");
	}

	//写入信息头
	is_ok = fwrite(fihead, sizeof(BITMAPINFOHEADER), 1, out_bmp);
	if (0 == is_ok)
	{
		printf("write file failed!!!\n");
	}

	fseek(in_bmp, fhead->bfOffBits, SEEK_SET);                                 //偏移到图像像素区

	RGBQUAD buf[2000] = { 0 };                                                 //用来读取像素值的缓冲区

	
	DWORD temp = 0;
	DWORD count = 0;
	int   buf_count = 0;
	while (!feof(in_bmp))
	{
		buf_count = 0;
		is_ok = fread(buf, sizeof(RGBQUAD), 1, in_bmp);
		if (0 == is_ok)
		{
			printf("read file failed!!!!\n");
		}
		while (buf_count < 2000 && count*4 < 2239488 )      //2000位缓冲区大小    2239488是根据信息头读出的大小
		{
			temp = 0;
			if (buf[buf_count].rgbBlue == 0 && buf[buf_count].rgbGreen == 0 && buf[buf_count].rgbRed == 0)
			{
				break;
			}
			if (buf[buf_count].rgbBlue == 255 && buf[buf_count].rgbGreen == 255 && buf[buf_count].rgbRed == 255)
			{
				break;
			}
			temp += (DWORD)buf[buf_count].rgbBlue;
			temp += (DWORD)buf[buf_count].rgbGreen;
			temp += (DWORD)buf[buf_count].rgbRed;
			temp /= 3;
		    buf[buf_count].rgbBlue = buf[buf_count].rgbGreen = buf[buf_count].rgbRed = (WORD)temp ;
			buf[buf_count].rgbReversed = 0;
			++buf_count;
			++count;
			//printf("像素大小:%ld\n",count);
		}
		is_ok = fwrite(buf, sizeof(buf), 1, out_bmp);
	}
	
	
	fclose(in_bmp);                    //关闭文件指针
	fclose(out_bmp);                   //关闭文件指针

	free(fhead);                       //释放内存
	free(fihead);                      //释放内存



	printf("success");
	system("pause");
	return 0;
}

 

<无标签>
举报
startstorm
发帖于2个月前 2回/52阅
顶部