http://members.easyshag.com/femaledesperation/cg01.html
http://members.easyshag.com/femaledesperation/gillian22.html#top
主题:贴一个BMP文件读写的程序吧,看到不少人问
bmpTest.h: 介绍BMP文件的格式及结构定义
bmpTest.cpp : 24bitBMP颜色数据到256色位图颜色数据的转换函数实现,具体算法可参考以 前的一个帖子
bmpTransfer.cpp:读入一个24bitBMP文件,转换成一个256色BMP文件的程序
编译完成后得到的程序,如bmpTransfer.exe
执行bmpTransfer file1 file2
file1是24bit的BMP位图源文件名,file2是新生成的256色位图文件名
可以用windows画板程序查看结果,似乎比直接用画板程序将24bitBMP存成256色BMP文件的转换效果要好哦。
/*************
bmpTest.h
**************/
#ifndef __BMPTEST_H_
#define __BMPTEST_H_
#include
typedef unsigned charBYTE;
typedef unsigned short WORD;
// BMP图像各部分说明如下
/***********
第一部分位图文件头
该结构的长度是固定的,为14个字节,各个域的依次如下:
2byte:文件类型,必须是0x4d42,即字符串"BM"。
4byte:整个文件大小
4byte:保留字,为0
4byte:从文件头到实际的位图图像数据的偏移字节数。
*************/
typedef struct
{
long imageSize;
long blank;
long startPosition;
void show(void)
{
printf("BMP Head:\n");
printf("Image Size:%d\n",imageSize);
printf("Image Data Start Position : %d\n",startPosition);
}
}BmpHead;
/*********************
第二部分位图信息头
该结构的长度也是固定的,为40个字节,各个域的依次说明如下:
4byte:本结构的长度,值为40
4byte:图像的宽度是多少象素。
4byte:图像的高度是多少象素。
2Byte:必须是1。
2Byte:表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。
4byte:指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。
4byte:指定实际的位图图像数据占用的字节数,可用以下的公式计算出来:
图像数据 = Width' * Height * 表示每个象素颜色占用的byte数(即颜色位数/8,24bit图为3,256色为1)
要注意的是:上述公式中的biWidth'必须是4的整数倍(不是biWidth,而是大于或等于biWidth的最小4的整数倍)。
如果biCompression为BI_RGB,则该项可能为0。
4byte:目标设备的水平分辨率。
4byte:目标设备的垂直分辨率。
4byte:本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的(颜色位数)次幂,如颜色位数为8,2^8=256,即256色的位图
4byte:指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色都是重要的。
***********************************/
typedef struct
{
longLength;
longwidth;
longheight;
WORDcolorPlane;
WORDbitColor;
longzipFormat;
longrealSize;
longxPels;
longyPels;
longcolorUse;
longcolorImportant;
void show(void)
{
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
{
BYTErgbBlue;
BYTErgbGreen;
BYTErgbRed;
BYTErgbReserved;
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
#include
//计算平方差的函数
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
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 filenamelike: xxx.bmp\n");
printf("filename2 : new 256 color BMP filename\n");
return -1;
}
BmpHeadheadBMP;
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**************
没有合适的资源?快使用搜索试试~ 我知道了~
真彩24位转256色(解决对齐问题)
共19个文件
pdb:2个
h:1个
txt:1个
5星 · 超过95%的资源 需积分: 36 18 下载量 56 浏览量
2016-11-23
19:15:12
上传
评论
收藏 1.91MB RAR 举报
温馨提示
网上大部分的转换代码都没有考虑对齐问题,好不容易找到这个,没有问题。 但是在批量处理图片时,需要修改两个地方 int usedTimes[4096] = {0};//12b int miniColor[4096]; 要改new出来,并把usedTimes初始化 在Transfer函数的最后要delete []usedTimes和delete []miniColor, 不然的话,批量处理堆栈会溢出。
资源推荐
资源详情
资源评论
收起资源包目录
真彩24位转256色.rar (19个子文件)
真彩24位转256色
testout.bmp 2KB
Debug
vc60.pdb 76KB
BMP_ReadWrite.ilk 203KB
BMP_ReadWrite.pdb 489KB
BMP_ReadWrite.exe 172KB
vc60.idb 129KB
BMP_ReadWrite.sbr 0B
BMP_ReadWrite.bsc 1.84MB
BMP_ReadWrite.obj 25KB
BMP_ReadWrite.pch 4.29MB
BMP_ReadWrite.opt 134KB
BMP_ReadWrite.dsw 551B
test.h 4KB
BMP_ReadWrite.dsp 3KB
读写BMP示例.txt 10KB
BMP_ReadWrite.positions 240B
BMP_ReadWrite.plg 1KB
BMP_ReadWrite.cpp 8KB
BMP_ReadWrite.ncb 57KB
共 19 条
- 1
资源评论
- Willardcsdn2016-11-24很实用的资料
BHY_
- 粉丝: 8273
- 资源: 34
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功