求DOS16位真彩模式下如何最简单的解码BMP?急!小弟给您磕头了!

lyzcom 2000-07-13 05:35:00
请问哪位好心的大哥,DOS下的16位真彩色模式中,解出24bit的BMP标准位图文件该怎么写?我要最简单的代码,只要能够显示24BIT的BMP图片就行。不考虑RLE等压缩格式!
您有代码,请送给小弟怠。我愿高分上送!!
...全文
249 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
flyingknight 2000-09-04
  • 打赏
  • 举报
回复
没意思,不如用dos4gw,那样好多了
满桌烟灰 2000-08-30
  • 打赏
  • 举报
回复
本程序使用Borland 3.1编译。
因为BMP图象格式中一般没有16位色的标准,所以我直接将24位色BMP转换为易被GETIMAGE命令使用的数据格式。

运行方式:bmp24t16 graph.bmp graph.pic

#pragma inline .386
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <alloc.h>
#include <string.h>
#include <dos.h>
#include "vesahigh.h"

#define farptr(p,l) (unsigned char far *)((unsigned char huge *)p+l)

void conv(unsigned char far *d,unsigned char *s,unsigned int length);

void main(int argc,char *argv[])
{
struct BMPHEAD bmphead;
struct BMPRGB bmprgb;
struct IMAGE far *image;
unsigned char far *p;
unsigned char far *linebuf;
unsigned int heightcount,width,height,l1,l2,color;
FILE *fp,*fp1;
unsigned long fileseek,offset,bytescolor;
unsigned char s[40],H,L;
int i;
unsigned char *bmpname="test.bmp ";
unsigned char *picname=" ";

if (argc>2)
{
printf("BMP File name:%s(%d)\nPIC File Name:%s(%d)",argv[1],strlen(argv[1]),argv[2],strlen(argv[2]));
strcpy(bmpname,argv[1]);
strcpy(picname,argv[2]);
}
else
{
printf("Exples : bmp24t16 test.bmp test.pic\n");
exit(0);
}
fp=fopen(bmpname,"rb");
if (fp==NULL) exit(1);
fread(&bmphead,sizeof(struct BMPHEAD),1,fp);
printf("Display BMP file Head Info :\n\n");
printf("BMP File Type :%04x\n",bmphead.type);
printf("Bmp File Length Byte :%ld(%08lx)\n",bmphead.filesize,bmphead.filesize);
printf("Resevered 1 :%d(%04x)\n",bmphead.resevered1,bmphead.resevered1);
printf("Resevered 2 :%d(%04x)\n",bmphead.resevered2,bmphead.resevered2);
printf("BMP Data To Head Offset :%ld(%08lx)\n",bmphead.offset,bmphead.offset);
printf("BMP Info Head Size :%ld(%08lx)\n",bmphead.infosize,bmphead.infosize);
printf("BMP Image Width :%ld(%08lx)\n",bmphead.width,bmphead.width);
printf("BMP Image Height :%ld(%08lx)\n",bmphead.height,bmphead.height);
printf("Video Bit Number :%d(%04x)\n",bmphead.planes,bmphead.planes);
printf("Pixel Color Bit Number :%d(%04x)\n",bmphead.bitcount,bmphead.bitcount);
printf("Image Data Compression type:%ld(%08lx)\n",bmphead.compression,bmphead.compression);
printf("Image Data Size :%ld(%08lx)\n",bmphead.sizeimage,bmphead.sizeimage);
printf("Video X Pixel :%ld(%08lx)\n",bmphead.xpels,bmphead.xpels);
printf("Video Y Pixel :%ld(%08lx)\n",bmphead.ypels,bmphead.ypels);
printf("Total color Number :%ld(%08lx)\n",bmphead.clrused,bmphead.clrused);
printf("Total color Number :%ld(%08lx)\n",bmphead.clrimport,bmphead.clrimport);
printf("\nBmp File Head Lenght :%d(%04x)\n",(unsigned char)sizeof(BMPHEAD),(unsigned char)sizeof(BMPHEAD));
while (!kbhit());getch();
initgraph(VESA_800_600);
fp=fopen(bmpname,"rb");
if (fp!=NULL)
{
rewind(fp);
fread(&bmphead,sizeof(struct BMPHEAD),1,fp);
if ((bmphead.type==0x4d42)&&(bmphead.bitcount==24))
{
if (bmphead.compression==0)
{
cprint(0,0,0xffff,0,"start read bmp file");
bytescolor=bmphead.bitcount/8;
offset=bmphead.width*bytescolor;
offset+=(offset%4)==0l?0l:(4-offset%4);
width=bmphead.width;
height=bmphead.height;
fileseek=bmphead.offset+offset*((long)height-1);
image=(IMAGE far *)farmalloc(width*2+4);
if (image==NULL)
{
farfree(image);
fclose(fp);
exit(1);
}
image->width=width;
image->height=1;
p=image->buffer;
p=farptr(p,0);
l1=width;
l2=width*2;
width*=bytescolor;
linebuf=(unsigned char far *)farmalloc(width);
if (linebuf==NULL)
{
farfree(linebuf);
fclose(fp);
exit(1);
}
linebuf=farptr(linebuf,0);
heightcount=0;
fp1=fopen(picname,"ab");
fwrite(&image->width,sizeof(unsigned int),1,fp1);
fwrite(&height,sizeof(unsigned int),1,fp1);
while (heightcount<height)
{
fseek(fp,fileseek,SEEK_SET);
fread(linebuf,sizeof(unsigned char),width,fp);
conv(p,linebuf,l1);
putimage(0,heightcount,image,COPY_PUT);
fwrite(p,sizeof(unsigned char),l2,fp1);
fileseek-=offset;
heightcount++;
}
fclose(fp1);
fclose(fp);
farfree(linebuf);
farfree(image);
while (!kbhit());
getch();
}
}
}
else
fclose(fp);
closegraph();
}

void conv(unsigned char far *d,unsigned char far *s,unsigned int length)
{
unsigned int dseg,doff,sseg,soff;
dseg=FP_SEG(d);
doff=FP_OFF(d);
sseg=FP_SEG(s);
soff=FP_OFF(s);
asm {
push ds
push es
/* lds si,d
les di,s*/
mov ax,dseg
mov es,ax
mov di,doff
mov ax,sseg
mov ds,ax
mov si,soff
mov ax,doff
mov di,ax
shr ax,4
mov dx,dseg
add ax,dx
mov es,ax
and di,0x000f
mov ax,soff
mov si,ax
shr ax,4
mov dx,sseg
add ax,dx
mov ds,ax
and si,0x000f
mov cx,length
cld
}
moveloop:
asm {
xor ax,ax
lodsb
shr ax,3
mov bx,ax
lodsb
shr ax,2
shl ax,5
or bx,ax
lodsb
shr ax,3
shl ax,11
or ax,bx
// xchg ah,al
stosw
loop SHORT moveloop
/* push cx
shr cx,2
rep movsd
pop cx
and cx,3
rep movsb*/
mov ax,di
shr ax,4
mov dx,es
add ax,dx
mov d+2,ax
and di,0x000f
mov ax,di
mov d,ax
pop es
pop ds
}
}
Kevin_qing 2000-08-29
  • 打赏
  • 举报
回复
读写bmp的类,你要自己改改
#define EDIT
//#define DEBUG
#ifndef __BMP_H_
#define __BMP_H_
#include <stdio.h>
#define DEBUGBMP
class Bmp:public Bitmap
{
protected:
int read(char far*);
void exchg(int,char far*);
void exchg(int);
struct Bmppal{
char blue;
char green;
char red;
char rev;
};
struct Bmphd{
int FLG;
long leng;
char rev1[4];
long ofst;
long structleng;
long width;
long height;
int plan;
int bits;
long cmpflg;
long datlen;
long res_v;
long res_h;
char rev2[8];
};


public:
int load(char far*);
long write(char far *);
void chgpal(int,int);
Bmp(){
palflg=FALSE;
palptr=NULL;
}
~Bmp(){
}
};
#define FOPNERR 1
#define REDERR 2
#define NOTBMP 3
#define XMSPOR 4
#define MEMPOR 5

#ifdef EDIT
#define NOTWRT 0
long Bmp::write(char far *fname)
{
FILE *fp;
fp=fopen(fname,"rb");
if(fp!=NULL)
{
fclose(fp);
cout<<fname<<" is already exist ,Do you want to overwritten? [Y/N]N";
char a;
do{
a=getch();
}while(a!='y'&&a!='Y'&&a!='n'&&a!='N'&&a!=13);
if(a=='n'||a=='N'||a==13)
return(NOTWRT);
cout<<"\bY\n";
}
fp=fopen(fname,"w+b");
Bmphd far *hd=new Bmphd;
hd->FLG=0x4d42;
hd->leng=(long)width*height+1078;
hd->rev1[0]=0;
hd->rev1[1]=0;
hd->rev1[2]=0;
hd->rev1[3]=0;
hd->ofst=1078;
hd->structleng=0x28;
hd->width=width;
hd->height=height;
hd->plan=1;
hd->bits=8;
hd->cmpflg=0;
hd->datlen=(long)width*height;
hd->res_v=0;
hd->res_h=0;
{
for (int i=0;i<8;i++)
hd->rev2[i]=0;
}
fwrite(hd,sizeof(Bmphd),1,fp);
Bmppal far*bpal=new Bmppal[256];
for(int i=0;i<256;i++)
{
bpal[i].rev=0;
bpal[i].blue=palptr[i].blue<<2;
bpal[i].green=palptr[i].green<<2;
bpal[i].red=palptr[i].red<<2;
}
fwrite(bpal,sizeof(Bmppal),256,fp);
delete bpal;
delete hd;
char far *dt=new char [width];
long ofst=(long)width*(height-1);
for(i=0;i<height;i++)
{
Xms::set_cd( (long)dt );
Xms::set_s(ofst);
Xms::copy(width);
fwrite(dt,1,width,fp);
ofst-=width;
}
fclose(fp);
return(TRUE);
}
#else
long Bmp::write(char far *fname)
{
cout<<"Write function not available!\n"<<fname<<endl;
getch();
return(FALSE);
}
#endif
void Bmp::exchg(int idx,char far*dat)
{
int tmp=width;
asm{
mov ax,idx
mov ah,al
push es
push di
push ds
push si
les di,dat
lds si,dat
mov cx,tmp
cld
}
xchgdat:
asm{
lodsb
cmp al,ah
jnz notidx
xor al,al
stosb
jmp next
}
notidx:
asm{
or al,al
jnz notzero
mov al,ah
stosb
jmp next
}
notzero:
asm inc di
next:
asm{
loop xchgdat
pop si
pop ds
pop di
pop es
}
}

void Bmp::chgpal(int x,int y)
{
unsigned char idx;
{
long tmpofst=(long)y*width+x;
set_cd((long)( (char far*)&idx) );
set_s(tmpofst);
copy(1L);
}
cout<<"Index color is "<<(int)idx<<endl;
getch();

if(idx==0)
return;
Pal::rgb_color tmp;

tmp.red=palptr[idx].red;
tmp.green=palptr[idx].green;
tmp.blue=palptr[idx].blue;

palptr[idx].green=palptr[0].green;
palptr[idx].blue=palptr[0].blue;
palptr[idx].red=palptr[0].red;

palptr[0].red=tmp.red;
palptr[0].blue=tmp.blue;
palptr[0].green=tmp.green;
char far *tmpdt=new char[width];
long ofst=0;
for(int i=0;i<height;i++)
{
Xms::set_cd((long)tmpdt);
Xms::set_s(ofst);
Xms::copy(width);
exchg(idx,tmpdt);
Xms::set_cs((long)tmpdt);
Xms::set_d(ofst);
Xms::copy(width);
ofst+=width;
}
}
int Bmp::load(char far*fn)
{
int a=read(fn);
if(a!=TRUE)
{
switch(a)
{
case FOPNERR:
cout<<"Open file "<<fn<<" Error!\n";
break;
case REDERR:
cout<<"Read file "<<fn<<" Error!\n";
break;
case NOTBMP:
cout<<"Not BMP file !\n";
break;
case XMSPOR:
cout<<"Xms memory is not enough!\n";
getch();
break;
case MEMPOR:
cout<<"Not enough memory!\n";
getch();
break;
default:
cout<<"Error No"<<a;
break;
}
getch();
return(FALSE);
}
return(TRUE);
}
int Bmp::read(char far*fnm)
{
FILE *fp;
Bmphd far*head=new Bmphd;
fp=fopen(fnm,"r+b");
if(fp==NULL)
return(FOPNERR);
int a=fread(head,1,sizeof(Bmphd),fp);
if(a==0)
return(REDERR);
if(head->FLG!=0x4d42)
return(NOTBMP);
width=head->width;
height=head->height;
Bmppal far* pal=new Bmppal[256];
fseek(fp,0x36L,SEEK_SET);
fread(pal,1,(sizeof(Bmppal)*256),fp);
Pal::rgb_color far*pal1=new Pal::rgb_color[256];
{
for(int i=0;i<256;i++)
{
pal1[i].red=pal[i].red>>2;
pal1[i].green=pal[i].green>>2;
pal1[i].blue=pal[i].blue>>2;
}
palptr=pal1;
}

fseek(fp,head->ofst,SEEK_SET);
dat=(char far*)farmalloc(width);
if(dat==NULL)
return(MEMPOR);
long bytes=(long)head->width*head->height;
unsigned kbreq=(bytes>>10)+1;
if(!Xms::alloc(kbreq))
return(XMSPOR);
long wbt=bytes-width;
do{
fread(dat,1,width,fp);
Xms::set_cs( (long)dat);
Xms::set_d(wbt);
Xms::copy(width);
wbt-=width;
}while(wbt>=0);
return(TRUE);
}
#endif

24位->16位565转换
void inline Color24To16(LPVOID dest,LPVOID src,DWORD nCount)
{
ASSERT(dest);
ASSERT(src);
_asm{
mov ecx,nCount
mov esi,src
mov edi,dest
cld
loop1:
lodsb //read B
shl eax,8
lodsb //read G
shl eax,8
lodsb //read R

shr al,3
mov bl,al //R8>>3 --> R5

shr eax,8 //pop R8
shl bx,6 //bits for G6

shr al,2 //G8>>2 -->G6
or bl,al //R5G6

shr eax,8 //pop G8

shl bx,5 //bits for B5

shr al,3 //B8>>3 -->B5
or bl,al //R5G6B5

mov ax,bx
stosw
loop loop1
}
}
//16位拷贝
colmode =true; 565->555
colmode =false; 565->565
void ColorCopy16(LPVOID dest,LPVOID src,DWORD width,DWORD height,DWORD pitch,BOOL colmode)
{
ASSERT(src);ASSERT(dest);
_asm{
mov esi,src
mov edi,dest
cld
mov edx,height
mov ecx,width
mov eax,colmode
or eax,eax
jnz loopcpy555
loopcpy64:
push edi
push ecx
shr ecx,1
repnz movsd
pop ecx
bt ecx,0
jnc isdw64
lodsw
stosw
isdw64:
pop edi
add edi,pitch
dec edx
jnz loopcpy64
}
return;
_asm{
loopcpy555:
push edi
push ecx
shr ecx,1
cpy555:
lodsd
mov ebx,eax
and eax,CLR32K
and ebx,CLR64K
shr ebx,1
or eax,ebx
stosd
loop cpy555
pop ecx
bt ecx,0
jnc isdw555
lodsw
mov bx,ax
and ax,word ptr CLR32K
and bx,word ptr CLR64K
shr bx,1
or ax,bx
stosw
isdw555:
pop edi
add edi,pitch
dec edx
jnz loopcpy555
}
}
如何确定是否是555的16-bits mode:
写任一像素为0xffff
读最高位是否为0
0->555
1->565
Kevin_qing 2000-08-29
  • 打赏
  • 举报
回复
补充一点
16bits有565和555的区别
halfdream 2000-07-17
  • 打赏
  • 举报
回复
一个没有用RLE之类编码的BMP,
24bits色BMP文件头54 个字节后就是位图数据,一个点用三字节。

1382:0100 42 4D 26 A9 00 00 00 00-00 00 36 00 00 00 28 00
1382:0110 00 00 8D 00 00 00 66 00-00 00 01 00 18 00 00 00
~~~~~\宽 ~~~~~~~\高
注意每行字节数必须为4的倍数。
:0x8D * 3 = 423 再加1 得424为一行的字节数。

1382:0120 00 00 F0 A8 00 00 C4 0E-00 00 C4 0E 00 00 00 00
1382:0130 00 00 00 00 00 00 0F 00-0F 00 00 0F 00 00 0F 00
~~~\位图开始每三字节一组,此图424字节一行。
1382:0140 00 00 0F 00 00 0F 00 00-0F 00 0F 00 00 10 00 07
1382:0150 2F 3F 77 A0 30 88 BF 3F-88 B0 6F 9F B0 90 A7 9F
现在是知道像素RGB的值, 就象SCUM说的那样做就行了。

至于显示,用VESA调用设定显示模式,然后再直接写屏,写0xa0000000开始的地址。。。
想来这个可能你会,相关资料也是比较容易找的。
茂奇软件 2000-07-17
  • 打赏
  • 举报
回复
I think you must access the address of
video adapter directly. you should find
an old book about it first. (i think the
job depend on the video adapter, SVGA,
and EVGA are different sytle.)
Jansen Zhu.
SCUM 2000-07-17
  • 打赏
  • 举报
回复
有一点你没搞清楚:16位色不是真彩色,是高彩色。

16位色也可以叫 64K 色,每像素占 2 字节,其位元占用如下:
蓝:0-4 绿:5-10 红:11-15

24位色也可以叫 16M 色,每像素占 3 字节,其位元占用如下:
蓝:0-7 绿:8-15 红:16-23

要显示 24 bit 的点时,只需将 24bit 的像素值(包括 rgb 三个值)通过移位
转化为 16 bit 就行了。

有一个公式可以参考:

r,g,b 为三原色值,t 为输出值:

r >>= 3;
g >>= 2;
b >>= 3;
t = (r << 11) | (g << 5) | b;
hoyle 2000-07-13
  • 打赏
  • 举报
回复
好像必须用位运算进行颜色转换

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧