🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Display a bitmap on screen, Visual C++

Started by
5 comments, last by GameDev.net 24 years, 7 months ago
I'm guessing this site could lead you in the right direction.. it's got a ton of links: http://www.ben2.ucla.edu/~permadi/gamelink/gamelink.html

or if you wanted to write your own image file parser (not hard for bitmap images) check out this website on graphic and 3d file formats: http://www.dcs.ed.ac.uk/%7Emxr/gfx/

Hope that helps.

Advertisement
Yiou're lucky, I just send John an email about this. Quite some length.....


Here they are (note, I only use 24 bits bitmaps, so these source are for 24
bits bitmaps only):

OK

//********************************************************************
// 24 bits bitmaps in SDI / MDI (MFC)
//********************************************************************
unsigned char *bits;
BITMAPFILEHEADER bmfh;
BITMAPINFO bmi;

void CPictureDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
// This code is for 24 Bit Bitmaps only.
int i,j,k; // These are the loop variables

ar << bmfh.bfType; //bmfh: Bit Map file Header
ar << bmfh.bfSize;
ar << bmfh.bfReserved1;
ar << bmfh.bfReserved2;
ar << bmfh.bfOffBits;

ar << bmi.bmiHeader.biSize; //bmi: Bit Map Info
ar << bmi.bmiHeader.biWidth;
ar << bmi.bmiHeader.biHeight;
ar << bmi.bmiHeader.biPlanes;
ar << bmi.bmiHeader.biBitCount;
ar << bmi.bmiHeader.biCompression;
ar << bmi.bmiHeader.biSizeImage;
ar << bmi.bmiHeader.biXPelsPerMeter;
ar << bmi.bmiHeader.biYPelsPerMeter;
ar << bmi.bmiHeader.biClrUsed;
ar << bmi.bmiHeader.biClrImportant;

//there is no colour table for 24 bit bitmaps
long int cnt = 0; // counter
for(i = 0; i < bmi.bmiHeader.biHeight; i++)
{
for(j = 0;j < bmi.bmiHeader.biWidth;j++)


for ( k = 1; k < 4; k++)


ar << bits[cnt];
cnt++;
}
}

for (j = 0;j < bmi.bmiHeader.biWidth % 4;j++)


ar << bits[cnt];
cnt++; //image has a double word boundary.
}
}

}
else
{
// TODO: add loading code here
int i, j, k;

ar >> bmfh.bfType; //bmfh:BitMap File Header
ar >> bmfh.bfSize ;
ar >> bmfh.bfReserved1;
ar >> bmfh.bfReserved2;
ar >> bmfh.bfOffBits;
ar >> bmi.bmiHeader.biSize; //bmi: Bit Map Info
ar >> bmi.bmiHeader.biWidth;
width = bmi.bmiHeader.biWidth;
ar >> bmi.bmiHeader.biHeight;
height = bmi.bmiHeader.biHeight;
ar >> bmi.bmiHeader.biPlanes;
ar >> bmi.bmiHeader.biBitCount;
ar >> bmi.bmiHeader.biCompression;
ar >> bmi.bmiHeader.biSizeImage;
ar >> bmi.bmiHeader.biXPelsPerMeter;
ar >> bmi.bmiHeader.biYPelsPerMeter;
ar >> bmi.bmiHeader.biClrUsed;
ar >> bmi.bmiHeader.biClrImportant;

if (bmi.bmiHeader.biBitCount==24)


// 24 bit bitmap ===============================
bits = (unsigned char *) malloc (((long int)((bmi.bmiHeader.biWidth * 3 +
bmi.bmiHeader.biWidth % 4) *
bmi.bmiHeader.biHeight)) *
sizeof(unsigned char));

long int cnt = 0;

for(i = 0;i < bmi.bmiHeader.biHeight;i++)
{
for(j = 0;j < bmi.bmiHeader.biWidth;j++)
{
for (k = 1;k < 4;k++)
{
ar >> bits[cnt];
cnt++;
}
}

for (j = 0;j < bmi.bmiHeader.biWidth % 4; j++)


ar>>bits[cnt];
cnt++;
}
}


}
else
{
MessageBox(NULL,"Sorry, this is not a 24 Bit Bitmap.", "File Open
Error",MB_ICONSTOP|MB_OK);
width = height = 0;

}
//MessageBox(NULL, "hallo", "ok", MB_OK);
}
}


void CPictureView::OnDraw(CDC* pDC)
{
CPictureDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

// TODO: add draw code for native data here
int ht;
int wh;

ht = pDoc->bmi.bmiHeader.biHeight;
wh = pDoc->bmi.bmiHeader.biWidth;
bmi = pDoc->bmi;
int bitcnt = (int)bmi.bmiHeader.biBitCount;
HDC hdc = ::GetDC(m_hWnd);

int yDiff, xDiff;
yDiff = GetScrollPos(SB_VERT);
xDiff = GetScrollPos(SB_HORZ);

SetDIBitsToDevice(hdc,
0,0,
(DWORD)wh,(DWORD)ht,
xDiff,0,
yDiff, (WORD)ht,
pDoc->bits,
(LPBITMAPINFO)&bmi,
DIB_RGB_COLORS);
}


//***********************
// If you use MFC, this method can easily be conerted for Dialog based. If
you want to do that, you make another CFile and a CArchive. with the right
parameters. if you need help about that, just ask.
//***********************


//***********************************************************
// The following MFC example can also be used in Win32, this was a test
program for me. (To write bitmaps) (My first attempt)
//***********************************************************

width = 100, height = 100;

int color = 0;

Buffer = new BYTE[width * height * 3];

for(int x = 0; x < (signed int)width * height * 3; x++)
{
Buffer[x] = color;
}

short res1=0;
short res2=0;
long pixoff=54;
long compression=0;
long cmpsize=0;
long colors=0;
long impcol=0;
char m1='B';
char m2='M';

DWORD widthDW = WIDTHBYTES(width * 24);

long bmfsize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
widthDW * height;
long byteswritten=0;

BITMAPINFOHEADER header;
header.biSize=40; // header size
header.biWidth=width;

header.biHeight=height;
header.biPlanes=1;
header.biBitCount=24; // RGB encoded, 24 bit
header.biCompression=BI_RGB; // no compression
header.biSizeImage=0;
header.biXPelsPerMeter=0;
header.biYPelsPerMeter=0;
header.biClrUsed=0;
header.biClrImportant=0;

FILE *fp;
fp=fopen("temp.bmp","wb");
if (fp==NULL)
{
//m_errorText="Can't open file for writing";
return;
}

// should probably check for write errors here...

fwrite((BYTE *)&(m1),1,1,fp); byteswritten+=1;
fwrite((BYTE *)&(m2),1,1,fp); byteswritten+=1;
fwrite((long *)&(bmfsize),4,1,fp); byteswritten+=4;
fwrite((int *)&(res1),2,1,fp); byteswritten+=2;
fwrite((int *)&(res2),2,1,fp); byteswritten+=2;
fwrite((long *)&(pixoff),4,1,fp); byteswritten+=4;

fwrite((BITMAPINFOHEADER *)&header,sizeof(BITMAPINFOHEADER),1,fp);
byteswritten+=sizeof(BITMAPINFOHEADER);

long row=0;
long RowIndex;
long row_size;
row_size=header.biWidth*3;
long ReadCount;
for (row=0;row RowIndex=(long unsigned)row*row_size;

// write a row
ReadCount=fwrite((void *)(Buffer+RowIndex),row_size,1,fp);
if (ReadCount!=1) {
//m_errorText="fwrite error\nGiving up";
break;
}
byteswritten+=row_size;

// pad to DWORD
for (DWORD count=row_size;count char dummy=0;
fwrite(&dummy,1,1,fp);
byteswritten++;
}

}

fclose(fp);

//*********************************************
// at the time I didn't feel like writing a loader the same way
//**********************************************

//*********************************************************
//******* The following is a real pain in the ass, for MFC
//*********************************************************

typedef LPBITMAPINFOHEADER PDIB;
#define DibWidth(lpbi) (UINT)(((LPBITMAPINFOHEADER)(lpbi))->biWidth)

#define DibHeight(lpbi) (UINT)(((LPBITMAPINFOHEADER)(lpbi))->biHeight)

#define DibColors(lpbi) ((RGBQUAD FAR *)((LPBYTE)(lpbi) +
(int)(lpbi)->biSize))

#ifdef WIN32
#define DibPtr(lpbi) ((lpbi)->biCompression == BI_BITFIELDS ?
(LPVOID)(DibColors(lpbi) + 3) : (LPVOID)(DibColors(lpbi) +
(UINT)(lpbi)->biClrUsed))
#else
#define DibPtr(lpbi) (LPVOID)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed)
#endif

#define DibInfo(pDIB) ((BITMAPINFO FAR *)(pDIB))

#define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <=
8 ? (int)(1 << (int)(lpbi)->biBitCount) : (int)(lpbi)->biClrUsed)

#define DibPaletteSize(lpbi) (DibNumColors(lpbi) * sizeof(RGBQUAD))

#define BFT_BITMAP 0x4d42

#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8)

#define DibWidthBytesN(lpbi, n) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth *
(UINT)(n))

#define DibWidthBytes(lpbi) DibWidthBytesN(lpbi, (lpbi)->biBitCount)

#define DibSizeImage(lpbi) ((lpbi)->biSizeImage == 0 ?
((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)(lpbi)->biHeight) :
(lpbi)->biSizeImage)

#ifndef BI_BITFIELDS
#define BI_BITFIELDS 3
#endif

#define FixBitmapInfo(lpbi) if((lpbi)->biSizeImage == 0) (lpbi)->biSizeImage
= DibSizeImage(lpbi); if((lpbi)->biClrUsed == 0) (lpbi)->biClrUsed =
DibNumColors(lpbi); if((lpbi)->biCompression == BI_BITFIELDS &&
(lpbi)->biClrUsed == 0)

PDIB m_Picture;
int m_Selected;
int m_CurrentWidth, m_CurrentHeight;

BOOL CEditImageDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here
m_Picture = DibOpenFile(m_FileToOpen);

m_CurrentWidth = DibWidth(m_Picture) + 100;
m_CurrentHeight = DibHeight(m_Picture);

m_PrevX = -1;
m_PrevY = -1;

Invalidate;

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}

PDIB CEditImageDlg: ibOpenFile(CString szFile)
{
HFILE fh;
DWORD dwLen, dwBits;
PDIB pdib;
LPVOID p;
OFSTRUCT of;
#if defined(WIN32) | | defined (_WIN32)
#define GetCurrentInstance() GetModuleHandle(NULL)
#else
#define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
#endif

fh = OpenFile(szFile, &of, OF_READ);
if(fh == -1)
{
HRSRC h;
h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);

#if defined(WIN32) | | defined(_WIN32)
if(h)
return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
#else
if(h)
fh = AccessResource(GetCurrentInstance(), h);
#endif
}

if(fh == -1)
return NULL;

pdib = DibReadBitmapInfo(fh);

if(!pdib)
return NULL;

dwBits = pdib->biSizeImage;
dwLen = pdib->biSize + DibPaletteSize(pdib) + dwBits;

p = GlobalReAllocPtr(pdib, dwLen, 0);

if(!p)
{
GlobalFreePtr(pdib);
pdib = NULL;
}
else
{
pdib = (PDIB)p;
}
if(pdib)
{
_hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib),
dwBits);
}
_lclose(fh);
return pdib;
}


PDIB CEditImageDlg: ibReadBitmapInfo(HFILE fh)
{
DWORD off;
HANDLE hbi = NULL;
int size;
int i;
int nNumColors;

RGBQUAD FAR *pRgb;
BITMAPINFOHEADER bi;
BITMAPCOREHEADER bc;
BITMAPFILEHEADER bf;
PDIB pdib;

if(fh == -1)
return NULL;

off = _llseek(fh, 0L, SEEK_CUR);

if(sizeof(bf) != _lread(fh, (LPSTR)&bf, sizeof(bf)))
return FALSE;

if(bf.bfType != BFT_BITMAP)
{
bf.bfOffBits = 0L;
_llseek(fh, off, SEEK_SET);
}

if(sizeof(bi) != _lread(fh, (LPSTR)&bi, sizeof(bi)))
return FALSE;

switch(size = (int)bi.biSize)
{
default:
case sizeof(BITMAPINFOHEADER):
break;

case sizeof(BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)&bi
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = (DWORD)bc.bcWidth;
bi.biHeight = (DWORD)bc.bcHeight;
bi.biPlanes = (UINT)bc.bcPlanes;
bi.biBitCount = (UINT)bc.bcBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

_llseek(fh, (LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),
SEEK_CUR);
break;
}

nNumColors = DibNumColors(&bi);

#if 0
if(bi.biSizeImage == 0)
bi.biSizeImage = DibSizeImage(&bi);

if(bi.biClrUsed == 0)
bi.biClrUsed = DibNumColors(&bi);
#else
FixBitmapInfo(&bi);
#endif

pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE, (LONG)bi.biSize + nNumColors *
sizeof(RGBQUAD));

if(!pdib)
return NULL;

*pdib = bi;

pRgb = DibColors(pdib);

if(nNumColors)
{
if(size == sizeof(BITMAPCOREHEADER))
{
_lread(fh, (LPVOID)pRgb, nNumColors * sizeof(RGBTRIPLE));

for(i = nNumColors - 1; i >=0; i--)
{
RGBQUAD rgb;
rgb.rgbRed = ((RGBTRIPLE FAR*)pRgb).rgbtRed;<BR> rgb.rgbBlue = ((RGBTRIPLE FAR*)pRgb).rgbtBlue;<BR> rgb.rgbGreen = ((RGBTRIPLE FAR*)pRgb).rgbtGreen;<BR> rgb.rgbReserved = (BYTE)0;<BR> }<BR> }<BR> else<BR> _lread(fh, (LPVOID)pRgb, nNumColors * sizeof(RGBQUAD));<BR>}<BR>if(bf.bfOffBits != 0L)<BR> _llseek(fh, off + bf.bfOffBits, SEEK_SET);<P>//m_ColorUsed = nNumColors;<BR>//UpdateData(FALSE);<P>return pdib;<BR>}<P>void CEditImageDlg::OnPaint()<BR>{<BR>CPaintDC dc(this); // device context for painting<P>// TODO: Add your message handler code here<BR>MoveWindow(0, 0, /*DibWidth(m_Picture)*/m_CurrentWidth,<BR>/*DibHeight(m_Picture)*/m_CurrentHeight+43);<BR>//GetDlgItem(IDC_STATIC)->MoveWindow(m_CurrentWidth - 100, 0, 80, 100);<BR>GetDlgItem(IDC_POINT_BUTTON)->MoveWindow(m_CurrentWidth - 90, 10, 70, 30);<BR>GetDlgItem(IDC_LINE_BUTTON)->MoveWindow(m_CurrentWidth - 90, 40, 70, 30);<BR>if(m_Picture != NULL)<BR>{<BR> ::StretchDIBits(dc.m_hDC, 0,0, DibWidth(m_Picture), DibHeight(m_Picture),<BR>0, 0, DibWidth(m_Picture), DibHeight(m_Picture), DibPtr(m_Picture),<BR>DibInfo(m_Picture), DIB_RGB_COLORS, SRCCOPY);<BR>}<P><BR>// Do not call CDialog::OnPaint() for painting messages<BR>}<P>//******************************************************<BR>** I have quite some more, but all the copy and paste *sigh*….well, I hope<BR>you have enough on these, and that you know there is only one real good<BR>method (the one for win32). I recommend you to take a close look at that<BR>one.<P>CJ<P><P>——————<BR>Dance with me……

Thanks CJ for all the code. It s definitely close to what I need. I couldn't get it to compile though. I was trying to use the middle section, the example you first used for displaying a bitmap for file to the screen. That was exactly what I needed but I couldn't get it to work. Any advice?

Thanks.

The middle code is code to write bitmaps, I can convert it to code which opens bitmaps and shows them on the screen though. Just let me know. What do you use, DirectX? OpenGL? DIB's? Name it and I'll make it

If you have a couple of days though........and if I can find the time between work, and college.....

------------------
Dance with me......

Sorry, misread your post I guess. What are the errors you get?

------------------
Dance with me......

Is there a site on the net containing code on how to load a bitmap picture from file and display it on the screen at a specified x,y coordinate?
(being used for ultima V style map)
This is how to do it in DirectDraw, if that's what you want: http://members.tripod.com/mxf_entertainment/tutorials/bitmaps.htm

------------------
- mallen22@concentric.net
- http://members.tripod.com/mxf_entertainment/

This topic is closed to new replies.

Advertisement