Archived

This topic is now archived and is closed to further replies.

Guest Anonymous Poster

Display a bitmap on screen, Visual C++

This topic is 6609 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
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)[i].rgbtRed;
rgb.rgbBlue = ((RGBTRIPLE FAR*)pRgb)[i].rgbtBlue;
rgb.rgbGreen = ((RGBTRIPLE FAR*)pRgb)[i].rgbtGreen;
rgb.rgbReserved = (BYTE)0;
}
}
else
_lread(fh, (LPVOID)pRgb, nNumColors * sizeof(RGBQUAD));
}
if(bf.bfOffBits != 0L)
_llseek(fh, off + bf.bfOffBits, SEEK_SET);

//m_ColorUsed = nNumColors;
//UpdateData(FALSE);

return pdib;
}

void CEditImageDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here
MoveWindow(0, 0, /*DibWidth(m_Picture)*/m_CurrentWidth,
/*DibHeight(m_Picture)*/m_CurrentHeight+43);
//GetDlgItem(IDC_STATIC)->MoveWindow(m_CurrentWidth - 100, 0, 80, 100);
GetDlgItem(IDC_POINT_BUTTON)->MoveWindow(m_CurrentWidth - 90, 10, 70, 30);
GetDlgItem(IDC_LINE_BUTTON)->MoveWindow(m_CurrentWidth - 90, 40, 70, 30);
if(m_Picture != NULL)
{
::StretchDIBits(dc.m_hDC, 0,0, DibWidth(m_Picture), DibHeight(m_Picture),
0, 0, DibWidth(m_Picture), DibHeight(m_Picture), DibPtr(m_Picture),
DibInfo(m_Picture), DIB_RGB_COLORS, SRCCOPY);
}


// Do not call CDialog::OnPaint() for painting messages
}

//******************************************************
** I have quite some more, but all the copy and paste *sigh*....well, I hope
you have enough on these, and that you know there is only one real good
method (the one for win32). I recommend you to take a close look at that
one.

CJ

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

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.

Share this post


Link to post
Share on other sites
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......

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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)

Share this post


Link to post
Share on other sites