正文

BMP图片支持2006-04-27 22:57:00

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

分享到:

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////BMP接口:      基于8位,16位位图的显示及贴图文件处理/////版本:         3.0/////程序:     沈华/////日期:     2004.12.26/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef __ZBMP_CPP#define __ZBMP_CPP //文件头14字节结构(不常用)struct { int type;  //2 long filesize;  //4 int reserved1;  //2 int reserved2;  //2 long imageoffset; //4 }BMPHEAD;  //14bytes //信息头结构40字节(同ICONINFO)struct { long size;     //4 long width;               //4 long height;               //4 int planes;                //2 int bitcount;              //2 long compress;             //4 long imagesize;     //4 long xpelspermeter;        //4 long ypelspermeter;        //4 long clrused;         //4 long clrimportant;         //4 }BMPINFO;     //40bytes //自定义的256色图片格式,主要用于3D引擎纹理贴图struct { long width;   //图片宽度 long height;   //图片高度 unsigned char colornum[256][3]; //已规格化(直接调色板接口排列顺序) }PICINFO; //图片高宽及色深全局变量unsigned long BMPWIDTH;unsigned long BMPHEIGHT;unsigned long BITDEPTH; //设置全局量和返回备用调色板号(打开成功返回大于零值)int G_OPENBMP(unsigned char far * filename,unsigned int tsbnum=0,char lookinfo=0);int G_SHOWBMP256(unsigned char far * filename,int sx=0,int sy=0,unsigned int tsbnum=0);int G_SHOWBMP565(unsigned char far * filename,int sx=0,int sy=0);//显示BMP图片的通用版本int G_SHOWBMP(unsigned char far * filename,int sx=0,int sy=0,unsigned int tsbnum=0);//显示PIC格式文件int G_SHOWPIC(unsigned char far * filename,int sx=0,int sy=0);//BMP格式转换为PIC格式int G_BMP2PIC(unsigned char far * bmpname,unsigned char far * picname); int G_OPENBMP(unsigned char far * filename,unsigned int tsbnum,char lookinfo){unsigned char colornum[256][4];FILE *fp; if( (fp=fopen(filename,"rb"))==NULL)  {fclose(fp);return 0;} if(lookinfo!=-1)  {fread(&BMPHEAD,1,sizeof(BMPHEAD),fp);} //定位信息结构 fseek(fp,14,SEEK_SET); //读取信息结构数据 fread(&BMPINFO,1,sizeof(BMPINFO),fp); if(lookinfo) { G_CLS(0); G_PUTS("位图文件的格式信息",32,0); G_PUTS("按任意键退出",200,0); G_PRINTEN(0,20,"BMPHEAD:"); G_PRINTEN(0,35,"   filesize=%ldKb",BMPHEAD.filesize/1000); G_PRINTEN(0,50,"  reserved1=%d",BMPHEAD.reserved1); G_PRINTEN(0,65,"  reserved2=%d",BMPHEAD.reserved2); G_PRINTEN(0,80,"imageoffset=%ld",BMPHEAD.imageoffset); G_PRINTEN(160,20,"BMPINFO:"); G_PRINTEN(160,35,"          size=%ld",BMPINFO.size); G_PRINTEN(160,50,"         width=%ld",BMPINFO.width); G_PRINTEN(160,65,"        height=%ld",BMPINFO.height); G_PRINTEN(160,80,"        planes=%d",BMPINFO.planes); G_PRINTEN(160,95,"      bitcount=%d",BMPINFO.bitcount); G_PRINTEN(160,110,"      compress=%ld",BMPINFO.compress); G_PRINTEN(160,130,"     imagesize=%ldKb",BMPINFO.imagesize/1000); G_PRINTEN(160,145," xpelspermeter=%ld",BMPINFO.xpelspermeter); G_PRINTEN(160,160," ypelspermeter=%ld",BMPINFO.ypelspermeter); G_PRINTEN(160,175,"       clrused=%ld",BMPINFO.clrused); G_PRINTEN(160,190,"  clrimportant=%ld",BMPINFO.clrimportant); getch(); G_CLS(0); } //向全局变量赋值 BMPWIDTH=BMPINFO.width; BMPHEIGHT=BMPINFO.height; //确定是否压缩及256色格式 switch(BMPINFO.bitcount) { case 4:  BITDEPTH=4;break; case 8:  BITDEPTH=8;break; case 24:  BITDEPTH=24;break; } //不支持压缩或16色格式 if(BMPINFO.compress==1 || BITDEPTH==4)   {fclose(fp);return 0;} //不支持在256色模式下显示真彩格式图片即不支持抖动显示 if(G_BITWIDTH==1 && BITDEPTH==24)   {fclose(fp);return 0;} //256色格式设置调色板索引 if(BITDEPTH==8) {  fseek(fp,54,SEEK_SET);  fread(colornum,1,1024,fp);  for(unsigned int i=0;i<256;i++)   {   G_TSB[tsbnum][i][0]=(colornum[i][2])>>2;   G_TSB[tsbnum][i][1]=(colornum[i][1])>>2;   G_TSB[tsbnum][i][2]=(colornum[i][0])>>2;   } }fclose(fp);return tsbnum;} int G_SHOWBMP256(unsigned char far * filename,int sx,int sy,unsigned int tsbnum){FILE *fp; if( (fp=fopen(filename,"rb"))==NULL)  {fclose(fp);return 3;} unsigned char colorn[1024];//显示宽度支持至1024象素 long width=BMPWIDTH,height=BMPHEIGHT; long gy=height,gx=width,zy=0L,offn; long xoff=0L,yoff=0L; unsigned int bz8,bz565;  sx+=G_VMINX;  sy+=G_VMINY;  //left clip  if(sx<G_VMINX)   //超出左边界   {   xoff=abs(-sx);//扫描线缓存起始地址   gx=abs(width-xoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gx>(G_VMAXX-G_VMINX)){xoff=0;gx=(G_VMAXX-G_VMINX);}   if(sx<-width){xoff=width;gx=0;}   //图片显示到屏幕的X坐标   sx=0;   }  //right clip  case  if(sx>=G_VMAXX-width)   {   xoff=0;   gx=abs(G_VMAXX-sx);   if(sx>G_VMAXX){xoff=width;gx=0;}   sx=sx;   }  //no clip case  else   {   xoff=0;   gx=width;   sx=sx;   }  //up clip case  if(sy<G_VMINY)   //超出上边界   {   yoff=abs(-sy);   gy=abs(height-yoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gy>(G_VMAXY-G_VMINY)){gy=(G_VMAXY-G_VMINY);}   if(sy<-height){yoff=height;gy=0;}   //图片显示到屏幕的X坐标   sy=0;   }  //down clip case  if(sy>G_VMAXY-height)   {   yoff=0;   gy=abs(G_VMAXY-sy);   if(sy>G_VMAXY){yoff=height;gy=0;}   sy=sy;   }  else   {   yoff=0;   gy=height;   sy=sy;   }  sx-=G_VMINX;  sy-=G_VMINY;   width=(width+3)/4*4;  offn=1078L+(height-yoff-1L)*(width);   for(zy=0;zy<gy;zy++)   {   fseek(fp,(offn-zy*width+xoff),SEEK_SET);   fread(colorn,1,gx,fp);   switch(G_BITWIDTH)//测试扫描线内是否有换页   {   case 1: bz8=G_GETXY_YESC8(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz8){G_SETPAGE(G_PAGE[bz8-100]);}    break;   case 2: bz565=G_GETXY_YESC565(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz565){G_SETPAGE(G_PAGE[bz565-100]);}    break;   }   for(unsigned int x=0;x<gx;x++)     {     unsigned char c=colorn[x];     if(G_BITWIDTH==1)//256色模式显示256色文件      {      if(bz8) //无换页版本写点       {G_PUTPIXEL_NOC(x+sx,zy+sy,c);}      else //有换页版本写点       {G_PUTPIXEL(x+sx,zy+sy,c);}      }     if(G_BITWIDTH==2)//增强色模式显示256色文件      {      unsigned char r=(G_TSB[tsbnum][c][0])>>1;      unsigned char g=(G_TSB[tsbnum][c][1]);      unsigned char b=(G_TSB[tsbnum][c][2])>>1;      if(bz565)       {G_PUTPIXEL_NOC(x+sx,zy+sy,RGB565(r,g,b));}      else       {G_PUTPIXEL(x+sx,zy+sy,RGB565(r,g,b));}      }      }   }fclose(fp);return 0;} int G_SHOWBMP565(unsigned char far * filename,int sx,int sy){if(G_BITWIDTH==1)return 0;FILE *fp; if( (fp=fopen(filename,"rb"))==NULL)  {fclose(fp);return 3;} RGB24 colorn[1024];//显示宽度支持至1024象素 long width=BMPWIDTH,height=BMPHEIGHT; long gx=width; long gy=height; long zy=0L; int xoff=0,yoff=0; long offn; unsigned char r,g,b; unsigned int bz565;  sx=sx+G_VMINX;  sy=sy+G_VMINY;  //left clip  if(sx<G_VMINX)   //超出左边界   {   xoff=abs(-sx);//扫描线缓存起始地址   gx=abs(width-xoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gx>(G_VMAXX-G_VMINX)){xoff=0;gx=(G_VMAXX-G_VMINX);}   if(sx<-width){xoff=width;gx=0;}   //图片显示到屏幕的X坐标   sx=0;   }  //right clip  case  if(sx>=G_VMAXX-width)   {   xoff=0;   gx=abs(G_VMAXX-sx);   if(sx>G_VMAXX){xoff=width;gx=0;}   sx=sx;   }  //no clip case  else   {   xoff=0;   gx=width;   sx=sx;   }  //up clip case  if(sy<G_VMINY)   //超出上边界   {   yoff=abs(-sy);   gy=abs(height-yoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gy>(G_VMAXY-G_VMINY)){gy=(G_VMAXY-G_VMINY);}   if(sy<-height){yoff=height;gy=0;}   //图片显示到屏幕的X坐标   sy=0;   }  //down clip case  if(sy>G_VMAXY-height)   {   yoff=0;   gy=abs(G_VMAXY-sy);   if(sy>G_VMAXY){yoff=height;gy=0;}   sy=sy;   }  else   {   yoff=0;   gy=height;   sy=sy;   }  sx-=G_VMINX;  sy-=G_VMINY;  width=((width*3)/4)*4+(width*3)%4+width%4;  offn=54L+(height-yoff-1)*width;   for(zy=0;zy<gy;zy++)   {   fseek(fp,(offn-zy*width+xoff*G_BITWIDTH),SEEK_SET);   fread(colorn,1,gx*3L,fp);   bz565=G_GETXY_YESC565(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);   if(bz565){G_SETPAGE(G_PAGE[bz565-100]);}   for(unsigned int x=0;x<gx;x++)     {      unsigned char b=((colorn[x].red)>>3)&0x1f;      unsigned char g=((colorn[x].green)>>2)&0x3f;      unsigned char r=((colorn[x].blue>>3))&0x1f;     if(bz565)      {G_PUTPIXEL_NOC(x+sx,zy+sy,RGB565(r,g,b));}     else      {G_PUTPIXEL(x+sx,zy+sy,RGB565(r,g,b));}     }   }fclose(fp);return 0;} int G_SHOWPIC(unsigned char far * filename,int sx,int sy){FILE *fp; if( (fp=fopen(filename,"rb"))==NULL)  {fclose(fp);return 3;} //读取信息头 fread((char *)&PICINFO,1,sizeof(PICINFO),fp); long width=PICINFO.width,height=PICINFO.height; unsigned char colorn[1024]; unsigned char colornum[256][3]; long gx=width; long gy=height; long zy=0L; int xoff=0,yoff=0; long offn=776L; unsigned char r,g,b; unsigned int bz8,bz565;  //读取调色板  fseek(fp,8,SEEK_SET);  fread(colornum,1,768,fp);  GDX=FP_OFF(colornum);GES=FP_SEG(colornum);  GCX=256;GBX=0;GAX=0x1012;  int86x(0x10,&regs,&regs,&sregs);  sx=sx+G_VMINX;  sy=sy+G_VMINY;  //left clip  if(sx<G_VMINX)   //超出左边界   {   xoff=abs(-sx);//扫描线缓存起始地址   gx=abs(width-xoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gx>(G_VMAXX-G_VMINX)){xoff=0;gx=(G_VMAXX-G_VMINX);}   if(sx<-width){xoff=width;gx=0;}   //图片显示到屏幕的X坐标   sx=0;   }  //right clip  case  if(sx>=G_VMAXX-width)   {   xoff=0;   gx=abs(G_VMAXX-sx);   if(sx>G_VMAXX){xoff=width;gx=0;}   sx=sx;   }  //no clip case  else   {   xoff=0;   gx=width;   sx=sx;   }  //up clip case  if(sy<G_VMINY)   //超出上边界   {   yoff=abs(-sy);   gy=abs(height-yoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gy>(G_VMAXY-G_VMINY)){gy=(G_VMAXY-G_VMINY);}   if(sy<-height){yoff=height;gy=0;}   //图片显示到屏幕的X坐标   sy=0;   }  //down clip case  if(sy>G_VMAXY-height)   {   yoff=0;   gy=abs(G_VMAXY-sy);   if(sy>G_VMAXY){yoff=height;gy=0;}   sy=sy;   }  else   {   yoff=0;   gy=height;   sy=sy;   }  sx-=G_VMINX;  sy-=G_VMINY;  width=(width+3)/4*4;   for(zy=0;zy<gy;zy++)   {   fseek(fp,(offn+(zy+yoff)*width),SEEK_SET);   fread(colorn,1,gx+xoff,fp);   switch(G_BITWIDTH)   {   case 1: bz8=G_GETXY_YESC8(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz8){G_SETPAGE(G_PAGE[bz8-100]);}    break;   case 2: bz565=G_GETXY_YESC565(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz565){G_SETPAGE(G_PAGE[bz565-100]);}    break;   }   for(unsigned int x=0;x<gx;x++)     {     unsigned char c=colorn[x+xoff];     if(G_BITWIDTH==1)      {      if(bz8)       {G_PUTPIXEL_NOC(x+sx,zy+sy,c);}      else       {G_PUTPIXEL(x+sx,zy+sy,c);}      }     if(G_BITWIDTH==2)      {      r=colornum[c][0]>>1;      g=colornum[c][1];      b=colornum[c][2]>>1;      if(bz565)       {G_PUTPIXEL_NOC(x+sx,zy+sy,RGB565(r,g,b));}      else       {G_PUTPIXEL(x+sx,zy+sy,RGB565(r,g,b));}      }    }  }fclose(fp);return 0;} int G_SHOWBMP(unsigned char far * filename,int sx,int sy,unsigned int tsbnum){if(G_BITWIDTH==1 && BITDEPTH==24){return 4;}FILE *fp; if( (fp=fopen(filename,"rb"))==NULL)  {fclose(fp);return 3;} long width=BMPWIDTH,height=BMPHEIGHT; long gy=height,gx=width,zy=0L,offn; long xoff=0L,yoff=0L; unsigned int bz8,bz565;  sx+=G_VMINX;  sy+=G_VMINY;  //left clip  if(sx<G_VMINX)   //超出左边界   {   xoff=abs(-sx);//扫描线缓存起始地址   gx=abs(width-xoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gx>(G_VMAXX-G_VMINX)){xoff=0;gx=(G_VMAXX-G_VMINX);}   if(sx<-width){xoff=width;gx=0;}   //图片显示到屏幕的X坐标   sx=0;   }  //right clip  case  if(sx>=G_VMAXX-width)   {   xoff=0;   gx=abs(G_VMAXX-sx);   if(sx>G_VMAXX){xoff=width;gx=0;}   sx=sx;   }  //no clip case  else   {   xoff=0;   gx=width;   sx=sx;   }  //up clip case  if(sy<G_VMINY)   //超出上边界   {   yoff=abs(-sy);   gy=abs(height-yoff);//裁剪后图片宽度   //如裁剪后图片宽度>屏幕取屏幕尺寸   if(gy>(G_VMAXY-G_VMINY)){gy=(G_VMAXY-G_VMINY);}   if(sy<-height){yoff=height;gy=0;}   //图片显示到屏幕的X坐标   sy=0;   }  //down clip case  if(sy>G_VMAXY-height)   {   yoff=0;   gy=abs(G_VMAXY-sy);   if(sy>G_VMAXY){yoff=height;gy=0;}   sy=sy;   }  else   {   yoff=0;   gy=height;   sy=sy;   }  sx-=G_VMINX;  sy-=G_VMINY;  switch(BITDEPTH) { case 4: break;//不支持16色格式 case 8: unsigned char colorn8[1024];  width=(width+3)/4*4;  offn=1078L+(height-yoff-1L)*(width);  for(zy=0;zy<gy;zy++)   {   fseek(fp,(offn-zy*width+xoff),SEEK_SET);   fread(colorn8,1,gx,fp);   switch(G_BITWIDTH)   {   case 1: bz8=G_GETXY_YESC8(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz8){G_SETPAGE(G_PAGE[bz8-100]);}    break;   case 2: bz565=G_GETXY_YESC565(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);    if(bz565){G_SETPAGE(G_PAGE[bz565-100]);}    break;   }   for(unsigned int x=0;x<gx;x++)     {     unsigned char c=colorn8[x];     if(G_BITWIDTH==1)      {      if(bz8)       {G_PUTPIXEL_NOC(x+sx,zy+sy,c);}      else       {G_PUTPIXEL(x+sx,zy+sy,c);}      }     if(G_BITWIDTH==2)      {      unsigned char r=(G_TSB[tsbnum][c][0])>>1;      unsigned char g=(G_TSB[tsbnum][c][1]);      unsigned char b=(G_TSB[tsbnum][c][2])>>1;      if(bz565)       {G_PUTPIXEL_NOC(x+sx,zy+sy,RGB565(r,g,b));}      else       {G_PUTPIXEL(x+sx,zy+sy,RGB565(r,g,b));}      }     }   }  break; case 24:  RGB24 colorn[1024];  width=((width*3)/4)*4+(width*3)%4+width%4;  offn=54L+(height-yoff-1)*width;  for(zy=0;zy<gy;zy++)   {   fseek(fp,(offn-zy*width+xoff*G_BITWIDTH),SEEK_SET);   fread(colorn,1,gx*3L,fp);   bz565=G_GETXY_YESC565(G_VMINX,G_VMINX+gx+sx,(unsigned int)zy+sy+G_VMINY);   if(bz565){G_SETPAGE(G_PAGE[bz565-100]);}   for(unsigned int x=0;x<gx;x++)     {      unsigned char b=((colorn[x].red)>>3)&0x1f;      unsigned char g=((colorn[x].green)>>2)&0x3f;      unsigned char r=((colorn[x].blue>>3))&0x1f;     if(bz565)      {G_PUTPIXEL_NOC(x+sx,zy+sy,RGB565(r,g,b));}     else      {G_PUTPIXEL(x+sx,zy+sy,RGB565(r,g,b));}     }   }  break; }fclose(fp);return 0;} int G_BMP2PIC(unsigned char far * bmpname,unsigned char far * picname){//读取BMP格式文件 FILE * bmpfp; if( (bmpfp=fopen(bmpname,"rb"))==NULL)  {fclose(bmpfp);return 3;} //跳过读取文件头 fseek(bmpfp,14,SEEK_SET); //读取信息头 fread(&BMPINFO,1,sizeof(BMPINFO),bmpfp); //确定是否压缩及256色格式 if (BMPINFO.compress!=0)  {fclose(bmpfp);return 3;} if(BMPINFO.bitcount!=8)  {fclose(bmpfp);return 3;}  unsigned char far * databuf=(unsigned char far *)farmalloc(BMPINFO.width); if(databuf==NULL)  {fclose(bmpfp);return 2;} //BMP格式第一行数据在文件中的指针 long offn=1078+(BMPINFO.height-1)*BMPINFO.width; //创建PIC格式文件 FILE * picfp; if( (picfp=fopen(picname,"wb"))==NULL)  {farfree(databuf);fclose(bmpfp);fclose(picfp);return 3;} long wd[2]; unsigned char colorpal1[256][4]; unsigned char colorpal2[256][3]; //从BMP格式文件读尺寸数据 wd[0]=(BMPINFO.width+3)/4*4; wd[1]=BMPINFO.height; //从BMP格式文件读调色板数据 fseek(bmpfp,54,SEEK_SET); fread(colorpal1,1,1024,bmpfp);  for(unsigned int i=0;i<256;i++)   {   colorpal2[i][0]=(colorpal1[i][2])>>2;   colorpal2[i][1]=(colorpal1[i][1])>>2;   colorpal2[i][2]=(colorpal1[i][0])>>2;   }  //写尺寸数据到PIC文件 fwrite(wd,4,2,picfp); //写调色板数据到PIC文件 fseek(picfp,8,SEEK_SET); fwrite(colorpal2,1,768,picfp); //写颜色数据到文件 for(unsigned int zy=0;zy<BMPINFO.height;zy++)  {   unsigned long cap=zy*BMPINFO.width;   fseek(bmpfp,(offn-cap),SEEK_SET);   fread(databuf,1,BMPINFO.width,bmpfp);   fseek(picfp,776+cap,SEEK_SET);   fwrite(databuf,1,BMPINFO.width,picfp);  }farfree(databuf);fclose(bmpfp);fclose(picfp);return 0;} #endif

阅读(4957) | 评论(0)


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

评论

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