正文

艺术再现BMP图像2006-05-16 21:44:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/mrli81/14210.html

分享到:

艺术再现BMP图像
  大家都用过PowerPoint吧,所谓艺术再现就是指把图像通过一些特效展现出来。这可以通过C语言来编写,感

兴趣的同学不妨通过上面学到的知识来自己动手编写一下。
文章转载
  下文是原tc256.com版主wujin的一篇文章,我们不妨拿来看看。
显示256色BMP位图
学习该文章应具备的预备知识:
(1)VGA显示系统
(2)BMP图像文件格式
(3)256色模式写屏以上文章在TC256专题站(http:\\tc256.51.net或http:\\wujin00.home.chinaren.com)均有

介绍。
学习该文章的补充知识:

1.VGA的DAC色彩寄存器知识  前面我已经讲过,16色和256色模式显示时,需要一张颜色表,以将显存的数据

“翻译”为屏幕上的点信息。  该颜色表在显卡芯片中其实对应一组寄存器,该寄存器就是DAC色彩寄存器,

在非真彩色的屏幕模式下,修改了DAC寄存器的值,就相当于修改了显存中某种色号对应的色彩信息。在VGA及

其兼容卡中,一共有256个该寄存器构成了一片存储单元,该单元就是显示器的DAC色表。  在256色BMP位图

中,也有这样一张色表,记录了该图片不同色彩信息对应的RGB值,该色表位于BMP文件54字节的位置处,按

照:B、G、R、alpha 的顺序排列的,但该RGB信息与DAC色彩寄存器的信息不同,DAC寄存器需要的颜色以6位表

示,即最大值为0x3F,而该BMP中的色表以8位表示,最大值为0xFF。因此,要将BMP位图的颜色信息换算为显示

的DAC信息,只需将从BMP获得的值右移2位即可。

 2.硬件无关屏幕初始化  现在我已经找到了硬件无关性初始化屏幕为640*480 256色模式的方法。这样一来

,只要在屏幕初始化之前先记录下原来的屏幕模式,程序结束后再恢到复原来的屏幕模式即可。
以下是完整的TC2程序代码:
/*--------------------256bmp.c----------------------*/
#include "dos.h"
#include "stdio.h"
selectpage(register char page) /*换页函数*/
{ union REGS r;
 r.x.ax=0x4f05;
 r.x.bx=0;
 r.x.dx=page;
 /*选择页面*/ 
int86(0x10,&r,&r);}
unsigned char set_SVGA_mode(int vmode) /*设置SVGA屏幕模式*/
{ union REGS r; 
r.x.ax=0x4f02;
 r.x.bx=vmode;
 int86(0x10,&r,&r);
 return(r.h.ah);
}
 unsigned int get_SVGA_mode() /*获取当前SVGA屏幕模式*/
{
 union REGS r;
 r.x.ax=0x4f03;
 int86(0x10,&r,&r);
 return(r.x.bx);
}
main()
{ char buffer[640],page_new=0,page_old=0;
 int i,j,k,n,r,g,b,savemode,width,length;
 long position; FILE *fp; puts("This is a 256 bmp viewer! Author:WuJin");
 puts("Input filename:"); /*输入要显示的BMP文件路径*/
 gets(buffer);
 if((fp=fopen(buffer,"rb"))==NULL)
 {printf("Can't open file: %s",buffer);
  return; }
 fseek(fp,28,SEEK_SET);
 fread(&i,2,1,fp);if(i!=8) /*检查是否为256色位图*/
 {puts("Not a 256 color bitmap!");
  fclose(fp);exit(0);
 }
 fseek(fp,18,SEEK_SET);
 fread(&width,4,1,fp);
 fread(&length,4,1,fp);
 savemode=get_SVGA_mode(); /*先保存原来的屏幕模式*/   set_SVGA_mode(0x101); /*硬件无关性初始化

屏幕为640*480 256色模式*/
 fseek(fp,54,SEEK_SET);
 for(i=0;i<256;i++) /*按照该图片的DAC色表设置色彩寄存器*/
 {b=fgetc(fp);
  g=fgetc(fp);
   r=fgetc(fp); /*获取R、G、B分量*/
  outportb(0x3c8,i);
  outportb(0x3c9,r>>2); /*右移是要转化为VGA的6位寄存器形式*/
  outportb(0x3c9,g>>2);
  outportb(0x3c9,b>>2);
  fgetc(fp); }
 k=(width%4)?(4-width%4):0; /*宽度修正值*/
for(j=length-1;j>=0;j--)
 {fread(buffer,width,1,fp);
  for(i=0,n=0;i<width;i++,n++)
  {position=j*640l+i; /*计算要显示点的显存位置*/ 
 page_new=position/65536; /*计算显示页*/ 
 if(page_new!=page_old)
 /*当显示页不同时更换页面,提高一定的输出速度*/
  {selectpage(page_new);page_old=page_new;}
  pokeb(0xa000,position%65536,buffer[n]); /*写到显存位置*/  }
  fseek(fp,k,SEEK_CUR); /*每行绘制完后修正宽度*/ }
 fclose(fp);
 getch(); set_SVGA_mode(savemode); /*恢复屏幕*/
}

阅读(3977) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册