🎉 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!

when displaying a bitmap color problem

Started by
5 comments, last by jobu 24 years, 6 months ago
May I suggest NOT posting entire source codes? Cut out the essential parts.

I haven't browsed through the code (I have stuff to do), but here's a few suggestions:

1) Check that the color mode match the image you are loading (I.e. a 256 color image won't display on a truecolor surface without conversion)

2) Check that the colormask is correct. I.e. your image may be 16-bit 555 but the screen is 565 or v.v..

3) Beware that the surface width is not the same as the amount of bytes per line. Use the lPitch property of the surface.

/Niels

<b>/NJ</b>
Advertisement
Due to a lack of time I only browsed through your code for a short time. I saw a couple of things from hwich I thought they should be changed, like;

1) In your loadbob thingy. You have
for (int indexy=0;indexyheight;indexy++)

2) I don't see you using the lPitch for your surface. You should add lPitch to your destination surface instead of using the width.

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

ive got the same problem - because the problem is in the book you use ("Windows Game Programming for Dummies")the book is good but... there is an error in the loadbob code:

>>>>for (int indexy=0;indexyheight;indexy++)
{
memcpy(destptr,sourceptr,bob->width);
destptr += bob->width;
sourceptr += bitmap->bitmapinfoheader.biWidth;
}<<<<

you must use lpitch in your code:
dest_ptr = dest_ptr + ddsd.lPitch;

Ive got the same problem, can you tell me where im supposed to put

dest_ptr = dest_ptr + ddsd.lpitch

ive tried putting it after the

dest_ptr = bob->width

but it keeps crashing, i would really appreciate any help

"I have realised that maths can explain everything. How it can is unimportant, I want to know why." -Me
What you need to do is replace
dest_ptr += bob->width;
With:
dest_ptr = dest_ptr + ddsd.lPitch;

Not just add it in afterwards.

Jonathan

when i run my program it displays about the top half of the image and the bottom half is garbage. it also displays the wrong colors course and i dont know why?
also when i save my image as 256 color the program crashes but when i save it as 24bit it just does what i said above.


heres the code:

// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN

#include windows.h
#include windowsx.h
#include mmsystem.h
#include math.h
#include ddraw.h
#include iostream.h
#include io.h
#include "ddutil.h"

// DEFINES ////////////////////////////////////////////////

// defines for windows
#define WINDOW_CLASS_NAME "WINCLASS1"
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
#define swidth 640
#define sheight 480
#define bpp 16
#define BITMAP_ID 0x4D42 // universal id for a bitmap
//#define _RGB16BIT(r,g,b) ((b&255) + ((g&255) << 8) + ((r&255) << 16))
#define _RGB16BIT(r,g,b) ((b%32) + ((g%32) << 5) + ((r%32) << 10))

typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;

typedef struct BITMAP_FILE_TAG
{
BITMAPFILEHEADER bitmapfileheader; // this contains the bitmapfile header
BITMAPINFOHEADER bitmapinfoheader; // this is all the info including the palette
PALETTEENTRY palette[256]; // we will store the palette here
UCHAR *buffer; // this is a pointer to the data

} BITMAP_FILE, *BITMAP_FILE_PTR;

typedef struct bitmap_obj_typ
{
int state;
int attr;
int x,y;
int width,height;
LPDIRECTDRAWSURFACE image;
} bitmapobj, *bitmap_obj_ptr;


int ginit(void *parms=NULL);
int gshutdown(void *parms=NULL);
int gmain(void *parms=NULL);
int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
int createbob(bitmap_obj_ptr bob, int width, int height,int attr, int flags);
int destroybob(bitmap_obj_ptr bob);
int drawbob(bitmap_obj_ptr bob,LPDIRECTDRAWSURFACE dest);
int loadbob(bitmap_obj_ptr bob, BITMAP_FILE_PTR bitmap16bit, int cx,int cy,int mode);

// GLOBALS ////////////////////////////////////////////////
HWND main_window_handle = NULL; // save the window handle
LPDIRECTDRAW lpdd;
LPDIRECTDRAWSURFACE lpddsprimary;
LPDIRECTDRAWSURFACE lpddsback;
LPDIRECTDRAWPALETTE lpddpal;
PALETTEENTRY palette[256];
DDSURFACEDESC ddsd;
DDBLTFX ddbltfx; // a direct draw surface description struct
DDSCAPS ddscaps; // a direct draw surface capabilities struct
HRESULT ddrval; // result back from dd calls
UCHAR *primarybuffer = NULL;
BITMAP_FILE bitmap16bit;
bitmapobj hero;

// FUNCTIONS //////////////////////////////////////////////
int createbob(bitmap_obj_ptr bob,
int width, int height,
int attr, int flags)
{
DDSURFACEDESC ddsd;
bob->state=1;
bob->attr=attr;
bob->image=NULL;
bob->x = bob->y = 0;
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
ddsd.dwWidth = bob->width=width;
ddsd.dwHeight = bob->height=height;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | flags;
if (lpdd->CreateSurface(&ddsd,&(bob->image),NULL)!=DD_OK)
return 0;

DDCOLORKEY color_key;
color_key.dwColorSpaceLowValue=0;
color_key.dwColorSpaceHighValue=0;
(bob->image)->SetColorKey(DDCKEY_SRCBLT, &color_key);
return 1;
}

int loadbob(bitmap_obj_ptr bob, BITMAP_FILE_PTR bitmap, int cx,int cy,int mode)
{
UCHAR *sourceptr,
*destptr;
DDSURFACEDESC ddsd;
if(mode==0)
{
cx=cx*(bob->width+1)+1;
cy=cy*(bob->height+1)+1;
}
sourceptr=bitmap->buffer+cy*bitmap->bitmapinfoheader.biWidth+cx;
ddsd.dwSize = sizeof(ddsd);
(bob->image)->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR,NULL);
destptr=(UCHAR *)ddsd.lpSurface;
for (int indexy=0;indexyheight;indexy++)
{
memcpy(destptr,sourceptr,bob->width);
destptr += bob->width;
sourceptr += bitmap->bitmapinfoheader.biWidth;
}
(bob->image)->Unlock(ddsd.lpSurface);
bob->state |= 2;
return 1;
}

int drawbob(bitmap_obj_ptr bob,LPDIRECTDRAWSURFACE dest) // surface to draw the bob on
{
// draw a bob at the x,y defined in the BOB
// on the destination surface defined in dest

RECT dest_rect, // the destination rectangle
source_rect; // the source rectangle

// fill in the destination rect
dest_rect.left = bob->x;
dest_rect.top = bob->y;
dest_rect.right = bob->x+bob->width-1;
dest_rect.bottom = bob->y+bob->height-1;

// fill in the source rect
source_rect.left = 0;
source_rect.top = 0;
source_rect.right = bob->width-1;
source_rect.bottom = bob->height-1;

// blt to destination surface
dest->Blt(&dest_rect, bob->image,
&source_rect,(DDBLT_WAIT | DDBLT_KEYSRC),
NULL);

// return success
return(1);
} // end Draw_BOB

int destroybob(bitmap_obj_ptr bob)
{
// destroy the BOB, simply release the surface

if (bob->image)
(bob->image)->Release();
else
return(0);

// return success
return(1);

} // end Destroy_BOB


LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context

// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
return(0);
} break;

case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return(0);
} break;

case WM_DESTROY:
{
// kill the application
PostQuitMessage(0);
return(0);
} break;

default:break;

} // end switch

// process any messages that we didn't take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{

WNDCLASS winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message

// first fill in the window class stucture
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;

// register the window class
if (!RegisterClass(&winclass))
return(0);

// create the window
if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
"Game console", // title
WS_POPUP | WS_VISIBLE,
0,0, // x,y
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN), // width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance
NULL))) // creation parms
return(0);

// save the window handle in a global
main_window_handle = hwnd;
ginit();
// enter main event loop
while(1)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;

// translate any accelerator keys
TranslateMessage(&msg);

// send the message to the window proc
DispatchMessage(&msg);
} // end if
gmain();
// main game processing goes here

} // end while
gshutdown();
// return to Windows like this
return(msg.wParam);
}


int ginit(void *parms)
{


// this function is where you do all the initialization
// for your game

// create object and test for error
if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK)
return(0);

// set cooperation level to windowed mode normal
if ((lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))!=DD_OK)
return(0);

// set the display mode
if ((lpdd->SetDisplayMode(swidth,sheight,bpp))!=DD_OK)
return(0);


// Create the primary surface
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
return 0;

Load_Bitmap_File(&bitmap16bit,"ship.bmp");
createbob(&hero,64,64,0,0);
loadbob(&hero,&bitmap16bit,0,0,1);
Unload_Bitmap_File(&bitmap16bit);


// return success
return(1);
} // end Game_Init

///////////////////////////////////////////////////////////

int gshutdown(void *parms)
{


// first release the primary surface
if (lpddsprimary!=NULL)
lpddsprimary->Release();


if (lpdd!=NULL)
lpdd->Release();
destroybob(&hero);

return(1);
} // end Game_Shutdown

///////////////////////////////////////////////////////////

int gmain(void *parms)
{
hero.x=100,hero.y=100;
if (KEY_DOWN(VK_ESCAPE) | | KEY_DOWN(VK_SPACE))
PostMessage(main_window_handle, WM_DESTROY,0,0);

drawbob(&hero,lpddsprimary);


// return success
return(1);

} // end Game_Main

///////////////////////////////////////////////////////////

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
// this function opens a bitmap file and loads the data into bitmap

int file_handle, // the file handle
index; // looping index

UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
OFSTRUCT file_data; // the file data information

// open the file if it exists
if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
return(0);

// now load the bitmap file header
_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));

// test if this is a bitmap file
if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
{
// close the file
_lclose(file_handle);

// return error
return(0);
} // end if

// now we know this is a bitmap, so read in all the sections

// first the bitmap infoheader

// now load the bitmap file header
_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));

// now load the color palette if there is one
if (bitmap->bitmapinfoheader.biBitCount == 8)
{
_lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));

// now set all the flags in the palette correctly and fix the reversed
// BGR RGBQUAD data format
for (index=0; index < 256; index++)
{
// reverse the red and green fields
int temp_color = bitmap->palette[index].peRed;
bitmap->palette[index].peRed = bitmap->palette[index].peBlue;
bitmap->palette[index].peBlue = temp_color;

// always set the flags word to this
bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
} // end for index

} // end if

// finally the image data itself
_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);

// now read in the image, if the image is 8 or 16 bit then simply read it
// but if its 24 bit then read it into a temporary area and then convert
// it to a 16 bit image

if (bitmap->bitmapinfoheader.biBitCount==8 | | bitmap->bitmapinfoheader.biBitCount==16)
{
// allocate the memory for the image
if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
{
// close the file
_lclose(file_handle);

// return error
return(0);
} // end if

// now read it in
_lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);

} // end if
else
{
// this must be a 24 bit image, load it in and convert it to 16 bit
// printf("\nconverting 24 bit image...");

// allocate temporary buffer
if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
{
// close the file
_lclose(file_handle);

// return error
return(0);
} // end if

// allocate final 16 bit storage buffer
if (!(bitmap->buffer=(UCHAR *)malloc(2*bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight)))
{
// close the file
_lclose(file_handle);

// release working buffer
free(temp_buffer);

// return error
return(0);
} // end if

// now read it in
_lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);

// now convert each 24 bit RGB value into a 16 bit value
for (index=0; indexbitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)
{
// extract RGB components (in BGR order), note the scaling
UCHAR blue = (temp_buffer[index*3 + 0] >> 3),
green = (temp_buffer[index*3 + 1] >> 3),
red = (temp_buffer[index*3 + 2] >> 3);

// build up 16 bit color word
USHORT color = _RGB16BIT(red,green,blue);

// write color to buffer
((USHORT *)bitmap->buffer)[index] = color;

} // end for index

// finally write out the correct number of bits
bitmap->bitmapinfoheader.biBitCount=16;

} // end if

#if 0
// write the file info out
printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
filename,
bitmap->bitmapinfoheader.biSizeImage,
bitmap->bitmapinfoheader.biWidth,
bitmap->bitmapinfoheader.biHeight,
bitmap->bitmapinfoheader.biBitCount,
bitmap->bitmapinfoheader.biClrUsed,
bitmap->bitmapinfoheader.biClrImportant);
#endif

// close the file
_lclose(file_handle);

// flip the bitmap
Flip_Bitmap(bitmap->buffer,
bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),
bitmap->bitmapinfoheader.biHeight);

// return success
return(1);

} // end Load_Bitmap_File

///////////////////////////////////////////////////////////

int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
// this function releases all memory associated with "bitmap"
if (bitmap->buffer)
{
// release memory
free(bitmap->buffer);

// reset pointer
bitmap->buffer = NULL;

} // end if

// return success
return(1);

} // end Unload_Bitmap_File

///////////////////////////////////////////////////////////


int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
{
// this function is used to flip upside down .BMP images

UCHAR *buffer; // used to perform the image processing
int index; // looping index

// allocate the temporary buffer
if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
return(0);

// copy image to work area
memcpy(buffer,image,bytes_per_line*height);

// flip vertically
for (index=0; index < height; index++)
memcpy(ℑ[((height-1) - index)*bytes_per_line],
&buffer[index*bytes_per_line], bytes_per_line);

// release the memory
free(buffer);

// return success
return(1);

} // end Flip_Bitmap

Yeah, thats what i did and it made it even worse, now the sprites frames are overlapping and completely distorted colours, i would really appreciate any help
"I have realised that maths can explain everything. How it can is unimportant, I want to know why." -Me

This topic is closed to new replies.

Advertisement