Importing BMP file in Turboc++ issue:BMP file is not being displayed properly in the output screenQuestion about cycle counting accuracy when emulating a CPUDisplay an array of color in CHow to read image file and display on screen in windows tasm dosboxReading the RGB values of the console color palettelinux to windows C++ byte arrayTips on creating a C++ DLL to be used from .NETDeciphering unsigned char*Not simple, converting long long from a char[8]How to read char array representing a pixel as unsigned intNarrowing Conversion of unsigned int to short unsigned intRead n bytes in a char array and return it as a doubleVector push_back error when compilingSimple Read then Write .bmp File C codeOrientation of a BMP file: upright or upside-down?

Installing Debian 10, upgrade to stable later?

Huffman Code in C++

What are these silver "sporks" for?

Is there precedent or are there procedures for a US president refusing to concede to an electoral defeat?

Playing Doublets with the Primes

Can anyone identify this unknown 1988 PC card from The Palantir Corporation?

Why doesn't a particle exert force on itself?

Endgame puzzle: How to avoid stalemate and win?

What does the coin flipping before dying mean?

Summer '19 Sandbox error: String index out of range: 0: Source

How important are good looking people in a novel/story?

Why increasing of the temperature of the objects like wood, paper etc. doesn't fire them?

How did the Apollo guidance computer handle parity bit errors?

How to use awk to extract data from a file based on the content of another file?

Changing stroke width vertically but not horizontally in Inkscape

What word describes the sound of an instrument based on the shape of the waveform of its sound?

How did the Force make Luke hard to hit in the Battle of Yavin?

Why can’t you see at the start of the Big Bang?

How to preserve a rare version of a book?

Emergency stop in plain TeX, pdfTeX, XeTeX and LuaTeX?

Reverse ColorFunction or ColorData

The selling of the sheep

My dual citizen son (US and Australia) wants to marry a US citizen but live in Australia

Picking a theme as a discovery writer



Importing BMP file in Turboc++ issue:BMP file is not being displayed properly in the output screen


Question about cycle counting accuracy when emulating a CPUDisplay an array of color in CHow to read image file and display on screen in windows tasm dosboxReading the RGB values of the console color palettelinux to windows C++ byte arrayTips on creating a C++ DLL to be used from .NETDeciphering unsigned char*Not simple, converting long long from a char[8]How to read char array representing a pixel as unsigned intNarrowing Conversion of unsigned int to short unsigned intRead n bytes in a char array and return it as a doubleVector push_back error when compilingSimple Read then Write .bmp File C codeOrientation of a BMP file: upright or upside-down?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








-2















I am trying to import Anand.BMP file in the graphics window of TCPP,

for this its source code is as follows

(NOTE: I have not mentioned the header files in the source code):



struct A

char type[2];
unsigned long size;
unsigned short int reserved1,reserved2;
unsigned long offset;
unsigned long width,height;
unsigned short int planes;
unsigned short int bits;
unsigned long compression;
unsigned long imagesize;
unsigned long xresolution,yresolution;
unsigned long ncolors;
unsigned long importantcolors;
HEADER;
huge DetectSvga()

return 2;

void show()

fstream File;
File.open("C:\TURBOC3\BIN\Anand.BMP",ios::in
void main()

clrscr();
int gd=DETECT,gm,a;
initgraph(&gd,&gm,"C:\TURBOC3\BGI");
installuserdriver("svga256",&DetectSvga);
show();
getch();
closegraph();



Now, i am not getting the BMP file in the graphics window,

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 think palette is not properly displayed through PaletteData pointer,

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;



As per suggestions I have modified the above codes as follows:
[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++)
=(*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();



Now,the above code is giving no errors but 2 warnings !!



WARNING :
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"



As a result image is not displaying in the output window
Output is displayed like this



I think y++; should be inside for (y=0;y<ys;y++)... loop

So,please analyse the edited code...










share|improve this question



















  • 6





    Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

    – Jesper Juhl
    Mar 19 at 16:54







  • 2





    As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

    – Mark Setchell
    Mar 19 at 17:21






  • 1





    Consider using CImg instead. It is modern C++ and easy to use cimg.eu

    – Mark Setchell
    Mar 20 at 9:20






  • 1





    @Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

    – Spektre
    Mar 20 at 9:35







  • 1





    @Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

    – Spektre
    Mar 20 at 9:38

















-2















I am trying to import Anand.BMP file in the graphics window of TCPP,

for this its source code is as follows

(NOTE: I have not mentioned the header files in the source code):



struct A

char type[2];
unsigned long size;
unsigned short int reserved1,reserved2;
unsigned long offset;
unsigned long width,height;
unsigned short int planes;
unsigned short int bits;
unsigned long compression;
unsigned long imagesize;
unsigned long xresolution,yresolution;
unsigned long ncolors;
unsigned long importantcolors;
HEADER;
huge DetectSvga()

return 2;

void show()

fstream File;
File.open("C:\TURBOC3\BIN\Anand.BMP",ios::in
void main()

clrscr();
int gd=DETECT,gm,a;
initgraph(&gd,&gm,"C:\TURBOC3\BGI");
installuserdriver("svga256",&DetectSvga);
show();
getch();
closegraph();



Now, i am not getting the BMP file in the graphics window,

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 think palette is not properly displayed through PaletteData pointer,

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;



As per suggestions I have modified the above codes as follows:
[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++)
=(*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();



Now,the above code is giving no errors but 2 warnings !!



WARNING :
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"



As a result image is not displaying in the output window
Output is displayed like this



I think y++; should be inside for (y=0;y<ys;y++)... loop

So,please analyse the edited code...










share|improve this question



















  • 6





    Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

    – Jesper Juhl
    Mar 19 at 16:54







  • 2





    As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

    – Mark Setchell
    Mar 19 at 17:21






  • 1





    Consider using CImg instead. It is modern C++ and easy to use cimg.eu

    – Mark Setchell
    Mar 20 at 9:20






  • 1





    @Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

    – Spektre
    Mar 20 at 9:35







  • 1





    @Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

    – Spektre
    Mar 20 at 9:38













-2












-2








-2








I am trying to import Anand.BMP file in the graphics window of TCPP,

for this its source code is as follows

(NOTE: I have not mentioned the header files in the source code):



struct A

char type[2];
unsigned long size;
unsigned short int reserved1,reserved2;
unsigned long offset;
unsigned long width,height;
unsigned short int planes;
unsigned short int bits;
unsigned long compression;
unsigned long imagesize;
unsigned long xresolution,yresolution;
unsigned long ncolors;
unsigned long importantcolors;
HEADER;
huge DetectSvga()

return 2;

void show()

fstream File;
File.open("C:\TURBOC3\BIN\Anand.BMP",ios::in
void main()

clrscr();
int gd=DETECT,gm,a;
initgraph(&gd,&gm,"C:\TURBOC3\BGI");
installuserdriver("svga256",&DetectSvga);
show();
getch();
closegraph();



Now, i am not getting the BMP file in the graphics window,

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 think palette is not properly displayed through PaletteData pointer,

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;



As per suggestions I have modified the above codes as follows:
[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++)
=(*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();



Now,the above code is giving no errors but 2 warnings !!



WARNING :
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"



As a result image is not displaying in the output window
Output is displayed like this



I think y++; should be inside for (y=0;y<ys;y++)... loop

So,please analyse the edited code...










share|improve this question
















I am trying to import Anand.BMP file in the graphics window of TCPP,

for this its source code is as follows

(NOTE: I have not mentioned the header files in the source code):



struct A

char type[2];
unsigned long size;
unsigned short int reserved1,reserved2;
unsigned long offset;
unsigned long width,height;
unsigned short int planes;
unsigned short int bits;
unsigned long compression;
unsigned long imagesize;
unsigned long xresolution,yresolution;
unsigned long ncolors;
unsigned long importantcolors;
HEADER;
huge DetectSvga()

return 2;

void show()

fstream File;
File.open("C:\TURBOC3\BIN\Anand.BMP",ios::in
void main()

clrscr();
int gd=DETECT,gm,a;
initgraph(&gd,&gm,"C:\TURBOC3\BGI");
installuserdriver("svga256",&DetectSvga);
show();
getch();
closegraph();



Now, i am not getting the BMP file in the graphics window,

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 think palette is not properly displayed through PaletteData pointer,

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;



As per suggestions I have modified the above codes as follows:
[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++)
=(*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();



Now,the above code is giving no errors but 2 warnings !!



WARNING :
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"



As a result image is not displaying in the output window
Output is displayed like this



I think y++; should be inside for (y=0;y<ys;y++)... loop

So,please analyse the edited code...







c++ bmp file-format turbo-c++ bgi






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 19 at 20:31









marc_s

588k13011281276




588k13011281276










asked Mar 19 at 16:49









SureshSuresh

1195




1195







  • 6





    Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

    – Jesper Juhl
    Mar 19 at 16:54







  • 2





    As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

    – Mark Setchell
    Mar 19 at 17:21






  • 1





    Consider using CImg instead. It is modern C++ and easy to use cimg.eu

    – Mark Setchell
    Mar 20 at 9:20






  • 1





    @Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

    – Spektre
    Mar 20 at 9:35







  • 1





    @Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

    – Spektre
    Mar 20 at 9:38












  • 6





    Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

    – Jesper Juhl
    Mar 19 at 16:54







  • 2





    As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

    – Mark Setchell
    Mar 19 at 17:21






  • 1





    Consider using CImg instead. It is modern C++ and easy to use cimg.eu

    – Mark Setchell
    Mar 20 at 9:20






  • 1





    @Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

    – Spektre
    Mar 20 at 9:35







  • 1





    @Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

    – Spektre
    Mar 20 at 9:38







6




6





Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

– Jesper Juhl
Mar 19 at 16:54






Do yourself a huge favour and stop using TurboC++ right now. It's several decades out of date, doesn't support modern C++, it will teach you bad habits (like void main() which is simply wrong), you will have to re-learn almost all C++ you learn with it once you move into a real job or open source project. You are wasting your time trying to use it.

– Jesper Juhl
Mar 19 at 16:54





2




2





As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

– Mark Setchell
Mar 19 at 17:21





As you are using Windows, you need to remind it not to feel free to add and remove characters it likes/dislikes from your files by adding the binary mode to the open() statement.

– Mark Setchell
Mar 19 at 17:21




1




1





Consider using CImg instead. It is modern C++ and easy to use cimg.eu

– Mark Setchell
Mar 20 at 9:20





Consider using CImg instead. It is modern C++ and easy to use cimg.eu

– Mark Setchell
Mar 20 at 9:20




1




1





@Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

– Spektre
Mar 20 at 9:35






@Suresh have you try to debug this? using breakpoints and tracing? is the palette read and set properly? are the pixels read with valid data? what happens if you do not change palette ? IIRC the outp(0x03c8,0); should be inside the for loop too ... Is the bmp image compatible with the fileformat you are decoding (BMP has many formats some are compressed, others use different bpp etc ...) did you set 256 color mode or not?

– Spektre
Mar 20 at 9:35





1




1





@Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

– Spektre
Mar 20 at 9:38





@Suresh here you got an alternative to BGI and BMP using VGA/VESA BIOS and 8bit PCX How to read image file and display on screen in windows tasm dosbox also take a look at Graphics rendering

– Spektre
Mar 20 at 9:38












1 Answer
1






active

oldest

votes


















1














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:



//---------------------------------------------------------------------------
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++)
=(*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++;

;
//---------------------------------------------------------------------------


And usage:



BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);


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 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...



Now what you have missing:




  1. 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 _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.



    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 #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 ...




  2. palette



    Your palette loading is suspicious I do not like it ... compare it with mine in the draw routine.



    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:



    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




  3. 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:



    (((bits*width)+31)>>5)<<2


    So just skip unused BYTEs in the file after each row decoded.



    You also do not use 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 ...



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:



#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


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 fseek and parameters are similar to mine FileSeek.



[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 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();

//---------------------------------------------------------------------------


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 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:



screenshot



As you can see I also render the palette for visual check an I got more getch() calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...






share|improve this answer




















  • 1





    @Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

    – Spektre
    Mar 21 at 18:02







  • 1





    @Suresh see [edit1]

    – Spektre
    Mar 22 at 7:50






  • 1





    @Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

    – Spektre
    Mar 22 at 16:07







  • 1





    @Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

    – Spektre
    Mar 22 at 16:13







  • 1





    @Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

    – Spektre
    Mar 22 at 17:15












Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55246188%2fimporting-bmp-file-in-turboc-issuebmp-file-is-not-being-displayed-properly-in%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














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:



//---------------------------------------------------------------------------
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++)
=(*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++;

;
//---------------------------------------------------------------------------


And usage:



BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);


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 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...



Now what you have missing:




  1. 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 _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.



    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 #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 ...




  2. palette



    Your palette loading is suspicious I do not like it ... compare it with mine in the draw routine.



    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:



    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




  3. 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:



    (((bits*width)+31)>>5)<<2


    So just skip unused BYTEs in the file after each row decoded.



    You also do not use 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 ...



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:



#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


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 fseek and parameters are similar to mine FileSeek.



[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 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();

//---------------------------------------------------------------------------


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 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:



screenshot



As you can see I also render the palette for visual check an I got more getch() calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...






share|improve this answer




















  • 1





    @Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

    – Spektre
    Mar 21 at 18:02







  • 1





    @Suresh see [edit1]

    – Spektre
    Mar 22 at 7:50






  • 1





    @Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

    – Spektre
    Mar 22 at 16:07







  • 1





    @Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

    – Spektre
    Mar 22 at 16:13







  • 1





    @Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

    – Spektre
    Mar 22 at 17:15
















1














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:



//---------------------------------------------------------------------------
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++)
=(*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++;

;
//---------------------------------------------------------------------------


And usage:



BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);


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 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...



Now what you have missing:




  1. 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 _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.



    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 #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 ...




  2. palette



    Your palette loading is suspicious I do not like it ... compare it with mine in the draw routine.



    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:



    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




  3. 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:



    (((bits*width)+31)>>5)<<2


    So just skip unused BYTEs in the file after each row decoded.



    You also do not use 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 ...



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:



#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


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 fseek and parameters are similar to mine FileSeek.



[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 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();

//---------------------------------------------------------------------------


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 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:



screenshot



As you can see I also render the palette for visual check an I got more getch() calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...






share|improve this answer




















  • 1





    @Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

    – Spektre
    Mar 21 at 18:02







  • 1





    @Suresh see [edit1]

    – Spektre
    Mar 22 at 7:50






  • 1





    @Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

    – Spektre
    Mar 22 at 16:07







  • 1





    @Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

    – Spektre
    Mar 22 at 16:13







  • 1





    @Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

    – Spektre
    Mar 22 at 17:15














1












1








1







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:



//---------------------------------------------------------------------------
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++)
=(*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++;

;
//---------------------------------------------------------------------------


And usage:



BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);


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 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...



Now what you have missing:




  1. 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 _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.



    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 #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 ...




  2. palette



    Your palette loading is suspicious I do not like it ... compare it with mine in the draw routine.



    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:



    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




  3. 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:



    (((bits*width)+31)>>5)<<2


    So just skip unused BYTEs in the file after each row decoded.



    You also do not use 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 ...



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:



#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


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 fseek and parameters are similar to mine FileSeek.



[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 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();

//---------------------------------------------------------------------------


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 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:



screenshot



As you can see I also render the palette for visual check an I got more getch() calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...






share|improve this answer















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:



//---------------------------------------------------------------------------
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++)
=(*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++;

;
//---------------------------------------------------------------------------


And usage:



BMP bmp;
bmp.load("Anand.bmp");
bmp.draw(target_VCL_bitmap,0,0);


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 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...



Now what you have missing:




  1. 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 _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.



    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 #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 ...




  2. palette



    Your palette loading is suspicious I do not like it ... compare it with mine in the draw routine.



    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:



    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




  3. 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:



    (((bits*width)+31)>>5)<<2


    So just skip unused BYTEs in the file after each row decoded.



    You also do not use 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 ...



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:



#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


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 fseek and parameters are similar to mine FileSeek.



[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 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();

//---------------------------------------------------------------------------


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 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:



screenshot



As you can see I also render the palette for visual check an I got more getch() calls as the DOSBOX bugged keyboard (probably because of CPU Clock tics timing control) drive me crazy ...







share|improve this answer














share|improve this answer



share|improve this answer








edited Apr 19 at 20:31









marc_s

588k13011281276




588k13011281276










answered Mar 21 at 9:18









SpektreSpektre

30.7k651222




30.7k651222







  • 1





    @Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

    – Spektre
    Mar 21 at 18:02







  • 1





    @Suresh see [edit1]

    – Spektre
    Mar 22 at 7:50






  • 1





    @Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

    – Spektre
    Mar 22 at 16:07







  • 1





    @Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

    – Spektre
    Mar 22 at 16:13







  • 1





    @Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

    – Spektre
    Mar 22 at 17:15













  • 1





    @Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

    – Spektre
    Mar 21 at 18:02







  • 1





    @Suresh see [edit1]

    – Spektre
    Mar 22 at 7:50






  • 1





    @Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

    – Spektre
    Mar 22 at 16:07







  • 1





    @Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

    – Spektre
    Mar 22 at 16:13







  • 1





    @Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

    – Spektre
    Mar 22 at 17:15








1




1





@Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

– Spektre
Mar 21 at 18:02






@Suresh read the text too all of this is mentioned there... 1. You need to use your file access routines as you have no access to the VCL ones no header will allow you those in 16 bit MS-DOS... 2. ignore the Graphics::TBitmap stuf use your PutPixel instead ... so instead of q[x0+x]=pal[*p]; will be PutPixel(x0+x,y0+ys-y-1,*p); and there will be no bmp and no q pointers ... nor ScanLine[] ... so even the header will be void draw(int x0,int y0)

– Spektre
Mar 21 at 18:02





1




1





@Suresh see [edit1]

– Spektre
Mar 22 at 7:50





@Suresh see [edit1]

– Spektre
Mar 22 at 7:50




1




1





@Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

– Spektre
Mar 22 at 16:07






@Suresh that line DWORD *q=(DWORD*)bmp->ScanLine[y0+ys-y-1]; will be gone (its just pointer to a scan line in my target VCL bmp but in your case you will have y position in PutPixel so you can delete that line completely (as I mentioned you should have no bmp and q in your code at all) the line PutPixel(x0+x,y0+ys-y-1,*p); inside the for loop covers it. So if you have undefined bmp symbol then you still forgot to get rid of it somewhere ... Why you want to use getpixel ? the bmp->ScanLine[y][x]=color is the same as your PutPixel(x,y,color);

– Spektre
Mar 22 at 16:07





1




1





@Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

– Spektre
Mar 22 at 16:13






@Suresh The q just holds pointer to actually processed scanline so I do not need to call bmp->ScanLine[y] for each pixel as its very slow ... accessing own pointer q[x] is faster (about 1000-10000 times)

– Spektre
Mar 22 at 16:13





1




1





@Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

– Spektre
Mar 22 at 17:15






@Suresh debug then ... place a breakpoint ... and then when it jumps on it use F7/F8 to step/trace and watch the variables for what is wrong... is the file opening, loading data correctly, palette loading, setting ... etc. Also you are in DOS BOX and using SVGA not sure if that requires some additional configuration of DOSBOX but it need a special BGI driver. Try VGA 320x200x8bit instead that is standard VGA and should be working no matter what. but have no Idea how to force it in BGI. Can you post your new code as an edit in your question (just to look if there is not some obvious problem)

– Spektre
Mar 22 at 17:15




















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55246188%2fimporting-bmp-file-in-turboc-issuebmp-file-is-not-being-displayed-properly-in%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript