////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////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,®s,®s,&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

评论