在Turboc ++问题中导入BMP文件:BMP文件未在输出屏幕中正确显示 [英] Importing BMP file in Turboc++ issue:BMP file is not being displayed properly in the output screen
问题描述
我正在尝试在 TCPP ,
的图形窗口中导入Anand.BMP文件为此,其源代码如下
(注意:在源代码中我没有提到头文件):
结构A{字符类型[2];无符号长号;unsigned short int reserved1,reserved2;无符号长偏移量;无符号的长,高;无符号的短int平面;无符号short int位;无符号长压缩;无符号长图像大小;无符号长xresolution,yresolution;无符号长ncolors;无符号的长重要颜色;} HEADER;巨大的DetectSvga(){返回2;}无效的show(){fstream文件;File.open("C:\\ TURBOC3 \\ BIN \\ Anand.BMP",ios :: in | ios :: binary);char ch;File.read((char *)& HEADER,sizeof(HEADER));无符号整数i;char ColorBytes [4];char * PaletteData;PaletteData =新字符[256 * 3];如果(PaletteData){for(i = 0; i <256; i ++){File.read(ColorBytes,4);PaletteData [(int)(i * 3 + 2)] = ColorBytes [0]> 2;PaletteData [(int)(i * 3 + 0)] = ColorBytes [2]> 2;}outp(0x03c8,0);for(i = 0; i <256 * 3; i ++)outp(0x03c9,PaletteData [i]);delete [] PaletteData;}for(i = 0; i< HEADER.height; i ++){for(int j = 0; j< HEADER.width;){File.read(& ch,1);putpixel(0+(j ++),0 + HEADER.height-i-1,ch);}}File.close();}无效main(){clrscr();int gd = DETECT,gm,a;初始化图形(& gd,& gm,"C:\\ TURBOC3 \\ BGI");installuserdriver("svga256",&DetectSvga);表演();getch();closegraph();}
现在,我没有在图形窗口中获取BMP文件,
即
图形窗口无法正确显示Anand.bmp.
如您所见,我还渲染了调色板以进行视觉检查,因为DOSBOX错误的键盘,我收到了更多的 Now, i am not getting the BMP file in the graphics window, I think palette is not properly displayed through PaletteData pointer, As per suggestions I have modified the above codes as follows: Now,the above code is giving no errors but 2 warnings !! WARNING : As a result image is not displaying in the output window I think Your decoding BMP code has a lot of problems... As I mentioned in my comments BMP is a mess with too many variations of format where you get lost very quickly so you need to have BMP format matching your decoding routine... Yes you change BMP to 8bpp but still its format is different to yours slightly ... Ok let use this image of yours (why to heck imgur is not supporting this???). After a while of (de)coding I come up with this C++/VCL code that decodes your bmp properly: And usage: Well as I do have different compiler (but also Borland/Embarcadero) and OS you need to ignore the VCL stuff and replace the rendering with your BGI ... Then change the Now what you have missing: header the header of BMP used is different than yours (there are a lot of variations out there that is why I suggested to use PCX instead). So take a look at mine You also do not check for the correct BMP format which is wrong and might lead to crashes so you should at least check the magic number and bpp, compression etc ... like I do Also do not forget to set the code alignment to 1 Byte (that is what the palette Your palette loading is suspicious I do not like it ... compare it with mine in the Also your setting VGA palette routine is wrong see how it should be done. So the target color should be set for each color not just once for whole palette so you need move the out inside loop: Image data you are not aligning the scan lines at all that is why your decoded image is shifted (skew like). According to Wiki each scan line is aligned to size: So just skip unused BYTEs in the file after each row decoded. You also do not use Also as you can see I loaded whole image into memory and decode from there. As you are in 16bit environment you might not want to do this as your OS might prevent you from allocating as much memory and also you are limited in memory size quite a lot... But I coded the whole stuff so I do not go back and forward so you should have no problems to port it to decoding directly from file like you have now ... [Edit1] here I dig some ancient example of file access from TCPP: just verify the usage with your inbuild help (CTRL+F1 while cursor is on a keyword there you will also see which include it needs if stdio is not the one) as I used this ~20 years ago and do not remember exactly... You will also need seek I think its called [Edit2] from your updated code its obvious you just copy paste code without thinking... I managed to code this in TCPP+DOSBOX (ouch man that was pain in the ass as DOSBOX keyboard conflicts borland shortcuts ...) You did not check the inbuild TCPP help and did not port the stuff correctly. For example yours I do not use BGI as I hate it instead I used direct memory access and VGA mode 13h but I code it so its similar to your BGI so you need to port that (remowing the gfxinit/exit and putpixel function bodies) if you want to use the BGI instead. I placed the BMP directly into As you can see I also render the palette for visual check an I got more 这篇关于在Turboc ++问题中导入BMP文件:BMP文件未在输出屏幕中正确显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! getch()
调用(可能是由于
i.e,
Graphics Window is not displaying Anand.bmp properly; Output is displayed like this
so how to fix it?
Here I am attaching my Anand.BMP file for convenience.
i.e, error is in this block of codes: for(i=0;i<256;i++)
{
File.read(ColorBytes,4);
PaletteData[(int)(i*3+2)]=ColorBytes[0]>>2;
PaletteData[(int)(i*3+0)]=ColorBytes[2]>>2;
}
[EDIT] : typedef unsigned long DWORD;
typedef unsigned int WORD;
typedef unsigned short BYTE;
//---------------------------------------------------------------------------
class BMP
{
public:
BYTE *data;
DWORD size;
#pragma pack(push,1)
struct _hdr
{
char ID[2];
DWORD size;
WORD reserved1[2]; // ?
DWORD offset;
DWORD reserved2; // ?
DWORD width,height;
WORD planes;
WORD bits;
DWORD compression;
DWORD imagesize;
DWORD xresolution,yresolution;
DWORD ncolors;
DWORD importantcolors;
};
#pragma pack(pop)
BMP(){ data=NULL; free(); }
~BMP(){ free(); }
void free(){ if (data) delete[] data; data=NULL; size=0; }
void load(char* filename)
{
FILE *hnd;
free();
if ((hnd=fopen(filename, "rb")) == NULL) return; // open file for read binary (not sure with the "b" check in build help)
size=fseek(hnd,0,2);
fseek(hnd,0,0);
BYTE data[256];
if (data==NULL) // not enough memory or empty file
{
size=0;
fclose(hnd);
return;
}
fread(data,256,1,hnd); // read 256 of 1 BYTES into data array
fclose(hnd); // close file
}
void draw(int x0,int y0)
{
_hdr *hdr=(_hdr*)data;
int x,y,xs,ys,skip;
DWORD pal[256],c; // palete to convert 8bpp -> 32bit VCL color
BYTE *p;
if (size<2) return;
if (hdr->ID[0]!='B') return; // check magic number
if (hdr->ID[1]!='M') return;
if (hdr->planes!=1) return; // check format
if (hdr->bits!=8) return;
if (hdr->compression!=0) return;
// palette
p=data+hdr->offset-(3*256);
p=data+sizeof(_hdr);
for (x=0;x<256;x++)
{
c =(*p) ; p++; // B
c|=(*p)<< 8; p++; // G
c|=(*p)<<16; p++; // R
p++; // A
pal[x]=c;
}
// image
xs=hdr->width;
ys=hdr->height;
p=data+hdr->offset;
skip=(((hdr->bits*hdr->width)+31)>>5)<<2; // compute scanline align
skip-=hdr->width;
for (y=0;y<ys;y++)
{
for (x=0;x<xs;x++,p++)
{
putpixel(x0+x,y0+ys-y-1,*p);
}
p+=skip; // handle align
}
y++;
}
};
//---------------------------------------------------------------------------
huge DetectSvga()
{
return 2;
}
void main()
{
clrscr();
int gd=DETECT,gm,a;
initgraph(&gd,&gm,"C:\\TURBOC3\\BGI");
installuserdriver("svga256",&DetectSvga);
BMP bmp;
bmp.load("C:\\TURBOC3\\BIN\\Anand.BMP");
bmp.draw(0,0);
getch();
closegraph();
}
1: for(x=0;x<256;x++)
: "Functions containing for
are not expanded inline"
2 : }
, i.e, at the end of void load()
function : "Functions containing some if
statements are not expanded inline"
Output is displayed like this y++;
should be inside for (y=0;y<ys;y++){...}
loop
So,please analyse the edited code...//---------------------------------------------------------------------------
class BMP
{
public:
BYTE *data;
DWORD size;
#pragma pack(push,1)
struct _hdr
{
char ID[2];
DWORD size;
WORD reserved1[2]; // ?
DWORD offset;
DWORD reserved2; // ?
DWORD width,height;
WORD planes;
WORD bits;
DWORD compression;
DWORD imagesize;
DWORD xresolution,yresolution;
DWORD ncolors;
DWORD importantcolors;
};
#pragma pack(pop)
BMP(){ data=NULL; free(); }
~BMP(){ free(); }
void free(){ if (data) delete[] data; data=NULL; size=0; }
void load(AnsiString filename) // load BMP into memory
{
int hnd;
free();
hnd=FileOpen(filename,fmOpenRead); // open file
if (hnd<0) return;
size=FileSeek(hnd,0,2); // seek to end of file to obtain filesize
FileSeek(hnd,0,0); // seek to start of file
data=new BYTE[size]; // allocate memory space for the BMP
if (data==NULL) // not enough memory or empty file
{
size=0;
FileClose(hnd);
return;
}
FileRead(hnd,data,size); // load the data
FileClose(hnd);
}
void draw(Graphics::TBitmap *bmp,int x0,int y0) // decode/render bitmap onto VCL bitmap
{
_hdr *hdr=(_hdr*)data;
int x,y,xs,ys,skip;
DWORD pal[256],c; // palete to convert 8bpp -> 32bit VCL color
BYTE *p;
if (size<2) return;
if (hdr->ID[0]!='B') return; // check magic number
if (hdr->ID[1]!='M') return;
if (hdr->planes!=1) return; // check format
if (hdr->bits!=8) return;
if (hdr->compression!=0) return;
// palette
p=data+hdr->offset-(3*256);
p=data+sizeof(_hdr);
for (x=0;x<256;x++)
{
c =(*p) ; p++; // B
c|=(*p)<< 8; p++; // G
c|=(*p)<<16; p++; // R
p++; // A
pal[x]=c;
}
// image
xs=hdr->width;
ys=hdr->height;
p=data+hdr->offset;
skip=(((hdr->bits*hdr->width)+31)>>5)<<2; // compute scanline align
skip-=hdr->width;
for (y=0;y<ys;y++)
{
DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; // target VCL bitmap scanline pointer
for (x=0;x<xs;x++,p++) q[x0+x]=pal[*p]; // copy pixels to target VCL bitmap
p+=skip; // handle align
}
y++;
}
};
//---------------------------------------------------------------------------
BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);
AnsiString
to char*
and change the file access routines to your environment (do not forget it should be binary access but IIRC even that did not always work in TCPP had problems with it in past while loading textures into my 3D renderer some control codes where processed regardless of binary access...
_hdr
struct and mimic yours ... The DWORD
is unsigned
32 bit int
, WORD
is unsigned
16 bit int
and BYTE
is unsigned
8 bit int
. I think that TCPP knows them but was ages i code in it so I might be wrong so if the case use relevant data types instead.#pragma pack
are for but not sure if TCPP support that. If not the align should be somewhere in the TCPP IDE settings probably in linker or compiler ...draw
routine.for(i=0;i<256*3;)
{
outp(0x03c8,i/3);
outp(0x03c9,PaletteData[i]); i++; // R
outp(0x03c9,PaletteData[i]); i++; // G
outp(0x03c9,PaletteData[i]); i++; // B
}
(((bits*width)+31)>>5)<<2
offset
which tells you where in the file the image data starts. That is important because the image data can be anywhere not just directly after palette as there might be more data present in the file like important colors etc ...#include <stdio.h>
FILE *hnd;
BYTE data[256];
if ((hnd=fopen("texture.txr", "rb")) == NULL) return; // open file for read binary (not sure with the "b" check in build help)
fread(data,256,1,hnd); // read 256 of 1 BYTES into data array
fclose(hnd); // close file
fseek
and parameters are similar to mine FileSeek
.fseek
does not return file size like mine which you would detect right away if you try to debug (F8/F7) ... So here my new C++ (TCPP compatible) code for this://---------------------------------------------------------------------------
#include <stdio.h>
#include <conio.h>
//---------------------------------------------------------------------------
typedef unsigned long DWORD;
typedef unsigned int WORD;
typedef unsigned char BYTE;
//---------------------------------------------------------------------------
char far* scr; // VGA screen
const _sx= 320; // physical screen size
const _sy= 200;
void gfxinit()
{
asm { mov ax,19
int 16
}
scr=(char far*)0xA0000000;
}
void gfxexit()
{
asm { mov ax,3
int 16
}
}
void clrscr()
{
asm { push es
mov ax,0xA000
mov es,ax
mov di,0x0000
sub ax,ax
mov cx,32000
rep stosw
pop es
}
}
void putpixel(int x,int y,char c)
{
unsigned int adr;
if ((x<_sx)&&(x>=0))
if ((y<_sy)&&(y>=0))
{
adr=x+(y*_sx);
scr[adr]=c;
}
}
//---------------------------------------------------------------------------
class BMP
{
public:
BYTE *data;
DWORD size;
#pragma pack(push,1)
struct _hdr
{
char ID[2];
DWORD size;
DWORD reserved1; // ?
DWORD offset;
DWORD reserved2; // ?
DWORD width,height;
WORD planes;
WORD bits;
DWORD compression;
DWORD imagesize;
DWORD xresolution,yresolution;
DWORD ncolors;
DWORD importantcolors;
};
#pragma pack(pop)
BMP(){ data=NULL; free(); }
~BMP(){ free(); }
void free(){ if (data) delete[] data; data=NULL; size=0; }
void load(char* filename);
void draw(int x0,int y0);
};
//---------------------------------------------------------------------------
void BMP::load(char* filename)
{
FILE *hnd;
free();
if ((hnd=fopen(filename, "rb")) == NULL) return; // open file for read binary (not sure with the "b" check in build help)
_hdr hdr;
hdr.ID[0]=0;
hdr.ID[1]=0;
hdr.size=0;
fread(&hdr,sizeof(_hdr),1,hnd); // read BMP header into memory
if (hdr.ID[0]=='B')
if (hdr.ID[1]=='M')
size=hdr.size; // get file size
fseek(hnd,0,0); // seek back to start
data=new BYTE[size];
if (data==NULL) // not enough memory or empty file
{
size=0;
fclose(hnd);
return;
}
fread(data,size,1,hnd); // read BMP into memory
fclose(hnd); // close file
}
//---------------------------------------------------------------------------
void BMP::draw(int x0,int y0)
{
_hdr *hdr=(_hdr*)data;
int x,y,xs,ys,skip;
BYTE *p;
if (size<2) return;
if (hdr->ID[0]!='B') return; // check magic number
if (hdr->ID[1]!='M') return;
if (hdr->planes!=1) return; // check format
if (hdr->bits!=8) return;
if (hdr->compression!=0) return;
// palette
p=data+sizeof(_hdr);
for (x=0;x<256;x++)
{
BYTE r,g,b;
b=*p>>2; p++;
g=*p>>2; p++;
r=*p>>2; p++;
p++;
outp(0x3C8,x);
outp(0x3C9,r);
outp(0x3C9,g);
outp(0x3C9,b);
}
// image
xs=hdr->width;
ys=hdr->height;
p=data+hdr->offset;
skip=(((hdr->bits*hdr->width)+31)>>5)<<2; // compute scanline align
skip-=hdr->width;
for (y=0;y<ys;y++,p+=skip)
for (x=0;x<xs;x++,p++)
putpixel(x0+x,y0+ys-y-1,*p);
}
//---------------------------------------------------------------------------
void main()
{
BMP bmp;
bmp.load("C:\\Anand.BMP");
gfxinit();
clrscr();
bmp.draw(0,16);
// draw palette
for (int x=0;x<256;x++)
for (int y=0;y<8;y++)
putpixel(x,y,x);
getch();
getch();
getch();
gfxexit();
}
//---------------------------------------------------------------------------
C:\
so I do not need to worry about exe local paths ... You did have a lot of bugs in there like discarted data
for BMP storage, wrong palette code etc ... But the biggest bug you got was BYTE
definition as yours was 16 bit instead of 8 bit messing up everything... The code above works for me with this output:getch()
calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...