论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

C语言教程:一个BMP文件读写的程序

文章类别:C语言程序设计 | 发表日期:2010-11-1 9:28:26

一个BMP文件读写的程序

printf("infoHead Length:%d\n",Length);
 printf("width&height:%d*%d\n",width,height); 
 printf("colorPlane:%d\n",colorPlane);
 printf("bitColor:%d\n",bitColor);
 printf("Compression Format:%d\n",zipFormat);
 printf("Image Real Size:%d\n",realSize);
 printf("Pels(X,Y):(%d,%d)\n",xPels,yPels);
 printf("colorUse:%d\n",colorUse); 
 printf("Important Color:%d\n",colorImportant);
 }
}InfoHead;

/***************************
 第三部分 调色盘结构
 对于256色BMP位图,颜色位数为8,需要2^8 = 256个调色盘;
 对于24bitBMP位图,各象素RGB值直接保存在图像数据区,不需要调色盘,不存在调色盘区
 rgbBlue: 该颜色的蓝色分量。
 rgbGreen: 该颜色的绿色分量。
 rgbRed: 该颜色的红色分量。
 rgbReserved:保留值。
************************/
typedef struct
{
 BYTE rgbBlue;
 BYTE rgbGreen;
 BYTE rgbRed;
 BYTE rgbReserved;
 void show(void)
 {
 printf("Mix Plate B,G,R:%d %d %d\n",rgbBlue,rgbGreen,rgbRed); 
 }
}RGBMixPlate;

/****************************
 第四部分 图像数据区
 对于用到调色板的位图,图像数据就是该象素颜色在调色板中的索引值;
 对于真彩色图,图像数据就是实际的R、G、B值。
 2色图,用1位就可以表示该象素的颜色,所以1个字节可以表示8个象素。
 16色图,用4位可以表示一个象素的颜色,所以1个字节可以表示2个象素。
 256色图,1个字节刚好可以表示1个象素。
 真彩色图,3个字节才能表示1个象素。 
****************************/


//将24bit的象素颜色数据转换为256色图的图像数据(即索引值)
int Transfer(WORD *color24bit, int len, BYTE *Index, RGBMixPlate *mainColor);

#endif

/***************
 bmpTest.cpp
****************/
#include "bmpTest.h"
#include <string.h>
#include <assert.h>

//计算平方差的函数
int PFC(int color1, int color2)
{
 int x,y,z;
 x = (color1 & 0xf) - (color2 & 0xf);
 y = ((color1>>4) & 0xf) - ((color2>>4) & 0xf);
 z = ((color1>>8) & 0xf) - ((color2>>8) & 0xf);
 return (x*x + y*y + z*z);
};

//直接插入排序
int Sort1(int *src, int *attach, int n)
{
 int cur, cur1;
 int i,j,k=0;
 for (i = 1; i < n; i++)
 {
 cur = src[i];
 cur1 = attach[i];
 for (j = i - 1; j >= 0; j--)
 {
 if (cur > src[j])
 {
 src[j+1] = src[j];
 attach[j+1] = attach[j];
 }
 else
 break;
 }
 src[j+1] = cur;
 attach[j+1] = cur1;
 }
 return 0;
}

//快速排序
int Sort2(int *src, int *attach, int n)
{
 if (n <= 12)
 return Sort1(src, attach, n);
 int low = 1, high = n - 1;
 int tmp;
 while (low <= high)
 {
 while (src[low] >= src[0])
 {
 if (++low > n - 1)
 break;
 }
 while (src[high] < src[0])
 {
 if (--high < 1)
 break;
 }
 if (low > high)
 break;
 {
 tmp = src[low];
 src[low] = src[high];
 src[high] = tmp;
 tmp = attach[low];
 attach[low] = attach[high];
 attach[high] = tmp;
 }
 low++;
 high--;
 }

 
 {
 tmp = src[low - 1];
 src[low - 1] = src[0];
 src[0] = tmp;
 tmp = attach[low - 1];
 attach[low - 1] = attach[0];
 attach[0] = tmp;
 }
 if (low > 1)
 Sort2(src, attach, low - 1);
 if (low < n)
 Sort2(&src[low], &attach[low], n - low);
 return 0;
}

//将24bit的象素颜色数据转换为256色图的图像数据(即索引值)
int Transfer(WORD *color24bit, int len, BYTE *Index, RGBMixPlate *mainColor){
 int usedTimes[4096] = {0};
 int miniColor[4096];
 for (int i = 0; i < 4096; i++)
 miniColor[i] = i;
 i = 0;
 for (i = 0; i < len; i++)
 {
 assert(color24bit[i] < 4096);
 usedTimes[color24bit[i]]++;
 }

 int numberOfColors = 0;
 for (i = 0; i < 4096; i++)
 {
 if (usedTimes[i] > 0)
 numberOfColors++;
 }

 //对usedTimes进行排序,排序过程中minColor数组(保存了颜色值)也作与useTimes
 //数组相似的交换
 Sort2(usedTimes, miniColor, 4096);

 //usedTimes数组中是各颜色使用频率,从高到低排列,显然第numberOfColor个之后的都为0
 //miniColor数组中是相应的颜色数据
 //将前256个颜色数据保存到256色位图的调色盘中
 for (i = 0; i < 256; i++)
 {
 mainColor[i].rgbBlue = (BYTE)((miniColor[i]>>8)<<4);
 mainColor[i].rgbGreen = (BYTE)(((miniColor[i]>>4) & 0xf)<<4);
 mainColor[i].rgbRed = (BYTE)((miniColor[i] & 0xf)<<4);
 mainColor[i].rgbReserved = 0;
 }

 int *colorIndex = usedTimes;//用原来的useTimes数组来保存索引值
 memset(colorIndex, 0, sizeof(int) * 4096);
 
 if (numberOfColors <= 256)
 {
 for (i = 0; i < numberOfColors; i++)
 colorIndex[miniColor[i]] = i;
 }
 else//为第256之后的颜色在前256种颜色中找一个最接近的
 {
 for (i = 0; i < 256; i++)
 colorIndex[miniColor[i]] = i;
 
 int index, tmp, tmp1;
 for (i = 256; i < numberOfColors; i++)
 {
 tmp = PFC(miniColor[0], miniColor[i]);
 index = 0;
 for (int j = 1; j < 256; j++)
 {
 tmp1 = PFC(miniColor[j], miniColor[i]);
 if (tmp > tmp1)
 {
 tmp = tmp1;
 index = j;
 }
 }
 colorIndex[miniColor[i]] = index;
 }
 }
 //记录各点颜色数据的索引值,即256色位图的颜色数据
 for (i = 0; i < len; i++)
 {
 assert(colorIndex[color24bit[i]] < 256);
 Index[i] = colorIndex[color24bit[i]];
 }

 return 1; 
}

/********************
 bmpTransfer.cpp
********************/
#include "bmpTest.h"
#include <string.h>

int __cdecl main(int argc,char* argv[])
{
 if (argc < 3)
 {
 printf("Usage:\n");
 printf(" %s filename1 filename2\n", argv[0]);
 printf(" filename1 : source 24bit BMP filename like: xxx.bmp\n");
 printf(" filename2 : new 256 color BMP filename\n");
 return -1;
 }
 BmpHead headBMP;
 InfoHead infoHead; 
 FILE* p;
 char* filename = argv[1];
 p = fopen(filename,"rb");
 if (p == NULL)
 {
 printf("!!!file %s open failed.\n", filename);
 }

 printf("file %s open success.\n",filename); 
/********** read BMP head ********************/ 
 fseek(p,2,SEEK_CUR);
 fread(&headBMP,1,12,p);
 headBMP.show();
 fread(&infoHead,1,40,p);
 infoHead.show();
 if (infoHead.bitColor != 24)
 {
 fclose(p);
 printf("This is not a 24bit BMP file.\n");
 return -1;
 }
/*********** read Image Date **************/
 long nData = infoHead.realSize;
 BYTE* pColorData = new BYTE[nData];
 fread(pColorData,1,nData,p);
 printf("last 4 byte of color Data:%x %x %x %x\n",\
 pColorData[nData-4],pColorData[nData-3],\
 pColorData[nData-2],pColorData[nData-1]);

/*********** read file over ***************/
 int leftData = 0;
 char ch = 0;
 while (!feof(p))
 {
 fread(&ch,1,1,p);
 leftData++;
 }
 if (leftData)
 printf("%d bytes not read in file.\n", leftData);
printf("read file over.\n"); 
 if(!fclose(p))
 {
 printf("file close.\n");
 }
// 24位BMP文件信息都读出来了,可以查看打印信息

/************ 24bit到256色的颜色数据转换 *****************/
 BYTE* Index = new BYTE[nData/3];
 RGBMixPlate mainColor[256];
 memset(mainColor, 0, sizeof(mainColor));
 WORD* shortColor = new WORD[nData/3];
 int iRed, iGreen, iBlue;
 for (int i = 0; i < nData/3; i++)
 {//取RGB颜色的高4位
 iRed = pColorData[i*3]>>4;
 iGreen = pColorData[i*3+1]>>4;
 iBlue = pColorData[i*3+2]>>4;
 shortColor[i] = (iRed<<8) + (iGreen<<4) + iBlue;
 }
 delete []pColorData;
 //调用转换函数
 Transfer(shortColor, nData/3, Index, mainColor);

 delete []shortColor; 
//转换完成,256色位图的调色盘数据(保存在mainColor)和图像数据区的数据(保存在Index中)

/************ 写一个新的256色BMP文件 *******************/
 
//修改一下前面读出的BmpHead和InfoHead的结构信息
 headBMP.imageSize = 14 + 40 + 4*256 + nData/3; 
 // 4*256是调色盘的长度,nData/3是图像数据区长度
 headBMP.startPosition += 4*256; //新文件加上了调色盘部分
 infoHead.bitColor = 8; //颜色位数改为8
 infoHead.realSize = nData/3; //图像数据区长度
 
//写新文件
 char* newFile = argv[2];
 FILE *p1 = fopen(newFile,"wb");
 if (NULL == p1)
 {
 printf("open new file failed.\n");
 return -1;
 }
 char hh[2] = {0x42, 0x4D};
 fwrite(hh,1,2,p1); //BMP文件开头两字节, 0x4d42 = "BM"
 fwrite(&headBMP, 1, 12, p1); //BMP文件头 
 fwrite(&infoHead, 1, 40, p1); //BMP文件头信息 
 fwrite(mainColor, 1, sizeof(mainColor), p1);//写调色盘信息
 fwrite(Index, 1, nData/3, p1); //颜色数据
 fclose(p1);

 //释放分配的内存
 delete []Index;
 return 0;
}

视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058