在TC下显示24位BMP
虽然在TC显示24位图像上的速度远远比不上256色的速度快,但是真彩色色彩带给我们的视觉上的冲击是256色远远不能达到的。我们今天就来仔细描述下我对24位位图的理解。
1. 24位BMP文件结构
24位BMP文件结构和256色BMP文件结构很大部分都是一样的。这里为了简单
就只介绍其中一些最常用的部分,具体的结构大家可以参考一下256色BMP文件结构。
0012—0015 ::图像宽度
0016—0019 :图像高度
001c—001d :图像的颜色数(24位图的值是24,256色图的值是8)
0036—???? :所有点的颜色值(重点,因为只有这里和256色图的结构不一样)
图像的宽度和高度以及颜色数都很好理解,现在我想重点讲的是0036的部分。
在24位图像中,没有‘DAC色表’,也没有‘图像数据区’。唯一留给我们的只有图像上所有点的颜色值。因为每个颜色都用BGR三种颜色来表示,而每个颜色占用1个字节,所以在24位图像中,每1个点就占用了3个字节。
那没有‘DAC’色表,也没有‘数据图像区’我们怎么来显示图象呢?很简单,24位图给我们提供了个更加简单的方法:‘所有点的颜色值’。既然是所有点,那么只要把这些点按照他们的颜色重新画出来就是该图像完整的信息了。
2. 修正宽度值(难点)
读取一行所有点的颜色:
fread(buffer,width*sizeof(ColorBGR),1,fp); /*读取该行像素的所有点的颜色*/
吴进说过:为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。
其实他说错了,起码在24位真彩色图象上,他是错误的。真彩色每行的字节数如果不够4的整数倍同样也需要“00”来补齐。
If(width%4) fseek(fp,(4-width%4),SEEK_CUR);
/*当宽度不是4的整数倍的时候,把文件指针fp跳过用来补齐的那几个“00”*/
3. 画点
画点的过程也就是图象显示出来的过程。每一个点都有自己的颜色,这样才能展现出绚丽的色彩。所以我们在画每一个点之前,都必须为该点重新调整调色板。
setrgbpalette(1026,buffer[i].r>>3,buffer[i].g>>2,buffer[i].b>>3); /*重设每个点的颜色*/
putpixel(i,j,0); /*画点*/
经过以上的几个步骤,绚丽的真彩色图象就显现出来了。以下是我整理的代码,BGI驱动我采用了Jordan Hargraphix 编写的SVGA64K.BGI 请大家编译的时候务必要把该文件与源代码文件放在同一个目录下。大家在输入文件名的时候请注意大小写,后缀名BMP一定要大写。
#include "graphics.h"
#include "stdio.h"
int huge return_SVGA64K_mode(void)
{
return(3); /*把分辨率设置为640x480*/
}
typedef struct /*ColorBGR像素类型*/
{
unsigned char b;
unsigned char g;
unsigned char r;
}ColorBGR;
void main()
{
char fname[30]; /*文件名*/
int width,height,gd=DETECT,gm,i,j;
FILE *fp;
ColorBGR *buffer;
printf("Please input the 64K BMP filename: "); /*输入24位位图的文件名*/
gets(fname);
if((fp=fopen(fname,"rb"))==NULL) /*打开文件,并且判断文件是否存在*/
{
printf("Can't find file %s",fname);
getch();
exit(1);
}
installuserdriver("Svga64k",return_SVGA64K_mode);/*对于svga64k必需执行该函数以安装BGI驱动*/
initgraph(&gd,&gm,"");/* 执行TC默认的BGI初始化函数 */
fseek(fp,18,SEEK_SET);
fread(&width,4,1,fp); /*图象宽度*/
fread(&height,4,1,fp); /*图象长度*/
buffer=(ColorBGR *)malloc(width*sizeof(ColorBGR));/*为一行所有的像素的颜色开创空间,用来保存同一个宽度上的每个点的颜色值*/
fseek(fp,54,SEEK_SET); /*定位文件指针指向颜色存储区*/
for(j=height-1;j>=0;j--)
{
fread(buffer,width*sizeof(ColorBGR),1,fp); /*读取该行像素的所有点的颜色*/
if(width%4) fseek(fp,(4-width%4),SEEK_CUR); /*宽度修正*/
for(i=0;i<width;i++)
{
setrgbpalette(1026,buffer[i].r>>3,buffer[i].g>>2,buffer[i].b>>3); /*重设每个点的颜色*/
putpixel(i,j,0); /*画点*/
}
}
free(buffer);
fclose(fp);
getch();
closegraph();
}
补记:
也许有人会问:为什么256色图片显示的时候我们必须要换页,而真彩色24位的图片显示的时候却不用呢?
我的回答是:因为显示256色的时候用的是直接改写VRAM的技术,所以要换页。而我们这里用的显示24位真彩色的时候用的是画点的方法,所以跳过了换页的问题(交给putpixel去解决啦)。因此速度上肯定比不过直接改写VRAM来得快。所以大家如果有了自己的想法,不妨自己改写一下程序,说不定你能让真彩色图象显示得更快哦~(那是肯定的,因为我的这个方法是最最笨的法子)
小提示:如果你正在为你的程序不能达到800x600或者更加高的分辨率而苦恼的话,你不妨换个编程环境试试。个人极力推荐纯DOS编程。在纯DOS环境下,很容易就能达到1024x768的高分辨率。具体原因:去问‘比尔该死’,我也不知道。
纯DOS的环境需要:
一张DOS系统启动盘(软盘)
mouse.com(如果你找不到,在我的压缩包里面有)
mouse.com是鼠标驱动程序。如果不先执行它,那么你软件中的鼠标部分将不可用(因为你已经不在WINDOWS环境下了)
[attach]659[/attach]
[此贴子已经被作者于2004-08-25 19:11:41编辑过]