Don't completely understand - Bitmap issue
At the moment I'm reading Sams teach yourself game programming in 24 hours. In this book at some point you will be creating your own bitmap class. The thing is, this bitmap class is supposed to be for 256 colour bitmap images.
Now it gets even weirder, the bitmaps supplied with the book are 256 colour bitmap images and they work perfectly. But as soon as I would add something with plain old ms paint and save it again as a 256 colour bitmap image, it suddenly gets weird on the bottom if I run the game like you're having some codec problem and the rest is like placed the other way around, the left part is placed on the right end and the right end is pushed to the left.
To make it even more weird, as soon as I save it as a 24bits colour bitmap image, it suddenly works perfect again :S.
To make my question short, how come my own 256 colour images are resulting into these sort of problems and what makes 24bits images work in a class which is designed for 256 colour bitmap images?
It's not a greyscale picture is it? If it is then you probably need a 24-bit image and it only uses one of the color channels.
The only other explanation I can see is that some of your info is wrong.
The only other explanation I can see is that some of your info is wrong.
The left/right issue is probably due to not padding the lines to 32 bit boundaries. Every line of the bitmap needs to be padded to complete 32 bit.
Why the 24bit images work i can't say without knowing/seeing the bitmap class code. My guess it with 24 bit depth the line is padded right.
Why the 24bit images work i can't say without knowing/seeing the bitmap class code. My guess it with 24 bit depth the line is padded right.
@Endurion: I'm telling all that I know, but here you have the code.
The bitmap class code:
[Edit: Because scrolling the entire page for some code is not cool. - Oluseyi]
@iMalc: It's not a greyscale picture.
[Edited by - Oluseyi on January 7, 2005 10:53:51 PM]
The bitmap class code:
//-----------------------------------------------------------------// Bitmap Object// C++ Source - Bitmap.cpp//-----------------------------------------------------------------//-----------------------------------------------------------------// Include Files//-----------------------------------------------------------------#include "Bitmap.h"//-----------------------------------------------------------------// Bitmap Constructor(s)/Destructor//-----------------------------------------------------------------Bitmap::Bitmap() : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0){}// Create a bitmap from a fileBitmap::Bitmap(HDC hDC, LPTSTR szFileName) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0){ Create(hDC, szFileName);}// Create a bitmap from a resourceBitmap::Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0){ Create(hDC, uiResID, hInstance);}// Create a blank bitmap from scratchBitmap::Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor) : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0){ Create(hDC, iWidth, iHeight, crColor);}Bitmap::~Bitmap(){ Free();}//-----------------------------------------------------------------// Bitmap Helper Methods//-----------------------------------------------------------------void Bitmap::Free(){ // Delete the bitmap graphics object if (m_hBitmap != NULL) { DeleteObject(m_hBitmap); m_hBitmap = NULL; }}//-----------------------------------------------------------------// Bitmap General Methods//-----------------------------------------------------------------BOOL Bitmap::Create(HDC hDC, LPTSTR szFileName){ // Free any previous bitmap info Free(); // Open the bitmap file HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; // Read the bitmap file header BITMAPFILEHEADER bmfHeader; DWORD dwBytesRead; BOOL bOK = ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); if ((!bOK) || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmfHeader.bfType != 0x4D42)) { CloseHandle(hFile); return FALSE; } BITMAPINFO* pBitmapInfo = (BITMAPINFO*)(new BITMAPINFO_256); if (pBitmapInfo != NULL) { // Read the bitmap info header bOK = ReadFile(hFile, pBitmapInfo, sizeof(BITMAPINFOHEADER), &dwBytesRead, NULL); if ((!bOK) || (dwBytesRead != sizeof(BITMAPINFOHEADER))) { CloseHandle(hFile); Free(); return FALSE; } // Store the width and height of the bitmap m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth; m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight; // Skip (forward or backward) to the color info, if necessary if (pBitmapInfo->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) SetFilePointer(hFile, pBitmapInfo->bmiHeader.biSize - sizeof (BITMAPINFOHEADER), NULL, FILE_CURRENT); // Read the color info bOK = ReadFile(hFile, pBitmapInfo->bmiColors, pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD), &dwBytesRead, NULL); // Get a handle to the bitmap and copy the image bits PBYTE pBitmapBits; m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0); if ((m_hBitmap != NULL) && (pBitmapBits != NULL)) { SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN); bOK = ReadFile(hFile, pBitmapBits, pBitmapInfo->bmiHeader.biSizeImage, &dwBytesRead, NULL); if (bOK) return TRUE; } } // Something went wrong, so cleanup everything Free(); return FALSE;}BOOL Bitmap::Create(HDC hDC, UINT uiResID, HINSTANCE hInstance){ // Free any previous DIB info Free(); // Find the bitmap resource HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(uiResID), RT_BITMAP); if (hResInfo == NULL) return FALSE; // Load the bitmap resource HGLOBAL hMemBitmap = LoadResource(hInstance, hResInfo); if (hMemBitmap == NULL) return FALSE; // Lock the resource and access the entire bitmap image PBYTE pBitmapImage = (BYTE*)LockResource(hMemBitmap); if (pBitmapImage == NULL) { FreeResource(hMemBitmap); return FALSE; } // Store the width and height of the bitmap BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage; m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth; m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight; // Get a handle to the bitmap and copy the image bits PBYTE pBitmapBits; m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS, (PVOID*)&pBitmapBits, NULL, 0); if ((m_hBitmap != NULL) && (pBitmapBits != NULL)) { const PBYTE pTempBits = pBitmapImage + pBitmapInfo->bmiHeader.biSize + pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD); CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage); // Unlock and free the bitmap graphics object UnlockResource(hMemBitmap); FreeResource(hMemBitmap); return TRUE; } // Something went wrong, so cleanup everything UnlockResource(hMemBitmap); FreeResource(hMemBitmap); Free(); return FALSE;}BOOL Bitmap::Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor){ // Create a blank bitmap m_hBitmap = CreateCompatibleBitmap(hDC, iWidth, iHeight); if (m_hBitmap == NULL) return FALSE; // Set the width and height m_iWidth = iWidth; m_iHeight = iHeight; // Create a memory device context to draw on the bitmap HDC hMemDC = CreateCompatibleDC(hDC); // Create a solid brush to fill the bitmap HBRUSH hBrush = CreateSolidBrush(crColor); // Select the bitmap into the device context HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap); // Fill the bitmap with a solid color RECT rcBitmap = { 0, 0, m_iWidth, m_iHeight }; FillRect(hMemDC, &rcBitmap, hBrush); // Cleanup SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); DeleteObject(hBrush); return TRUE;}void Bitmap::Draw(HDC hDC, int x, int y, BOOL bTrans, COLORREF crTransColor){ if (m_hBitmap != NULL) { // Create a memory device context for the bitmap HDC hMemDC = CreateCompatibleDC(hDC); // Select the bitmap into the device context HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap); // Draw the bitmap to the destination device context if (bTrans) TransparentBlt(hDC, x, y, GetWidth(), GetHeight(), hMemDC, 0, 0, GetWidth(), GetHeight(), crTransColor); else BitBlt(hDC, x, y, GetWidth(), GetHeight(), hMemDC, 0, 0, SRCCOPY); // Restore and delete the memory device context SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); }}
//-----------------------------------------------------------------// Bitmap Object// C++ Header - Bitmap.h//-----------------------------------------------------------------#pragma once//-----------------------------------------------------------------// Include Files//-----------------------------------------------------------------#include <windows.h>//-----------------------------------------------------------------// Custom Data Types//-----------------------------------------------------------------struct BITMAPINFO_256{ BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[256];};//-----------------------------------------------------------------// Bitmap Class//-----------------------------------------------------------------class Bitmap{protected: // Member Variables HBITMAP m_hBitmap; int m_iWidth, m_iHeight; // Helper Methods void Free();public: // Constructor(s)/Destructor Bitmap(); Bitmap(HDC hDC, LPTSTR szFileName); Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance); Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor = RGB(0, 0, 0)); virtual ~Bitmap(); // General Methods BOOL Create(HDC hDC, LPTSTR szFileName); BOOL Create(HDC hDC, UINT uiResID, HINSTANCE hInstance); BOOL Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor); void Draw(HDC hDC, int x, int y, BOOL bTrans = FALSE, COLORREF crTransColor = RGB(255, 0, 255)); int GetWidth() { return m_iWidth; }; int GetHeight() { return m_iHeight; };};
[Edit: Because scrolling the entire page for some code is not cool. - Oluseyi]
@iMalc: It's not a greyscale picture.
[Edited by - Oluseyi on January 7, 2005 10:53:51 PM]
My first instinct would be to suggest that the use of Paint to edit the image is the problem... Paint does some weird things, IME, in the name of its IMHO very strange idea of "user friendliness".
Are you resizing the image when you edit it?
Have you tried hex-editing the original and modified BMPs to see if things are as you would expect (same header and colour table data)?
Have you tested the code with a blank (or solid-colour) image?
Are you resizing the image when you edit it?
Have you tried hex-editing the original and modified BMPs to see if things are as you would expect (same header and colour table data)?
Have you tested the code with a blank (or solid-colour) image?
Eww. You don't want to restrict your image type to something that silly.
Try a different bitmap handling class. In fact... I have one right here:
First the header file:
And for the sister source file:
I'm not going into too much detail about how things work. I went into more detail here on it, though not as much as I could have.
Anyway, you want to know the usage. Ok.
-Greven
Try a different bitmap handling class. In fact... I have one right here:
First the header file:
// BitMapObject.h#ifndef BITMAPOBJECT_H#define BITMAPOBJECT_H#pragma once// we need this for window stuff#include <windows.h>class BitMapObject{private: // memory dc HDC hdcMemory; // new bitmap! HBITMAP hbmNewBitMap; // old bitmap. HBITMAP hbmOldBitMap; // width & height as integers. int iWidth; int iHeight;public: // constructor BitMapObject(); // destructor ~BitMapObject(); // loads bitmap from a file void Load(HDC hdcCompatible, LPCTSTR lpszFilename); // creates a blank bitmap void Create(HDC hdcCompatible, int width, int height); // destroys bitmap and dc void Destroy(); // return width int GetWidth(); // return height int GetHeight(); // converts to HDC operator HDC();};#endif
And for the sister source file:
#include "bitmapobject.h"BitMapObject::BitMapObject(){ hdcMemory = NULL; hbmNewBitMap = NULL; hbmOldBitMap = NULL; iWidth = 0; iHeight = 0;}BitMapObject::~BitMapObject(){ // if the hdcMemory hasn't been destroyed, do so if(hdcMemory) Destroy();}void BitMapObject::Load(HDC hdcCompatible, LPCTSTR lpszFilename){ // if hdcMemory isn't null, make it so captain! if(hdcMemory) Destroy(); // create memory dc. hdcMemory = CreateCompatibleDC(hdcCompatible); // load the bitmap hbmNewBitMap = (HBITMAP)LoadImage(NULL, lpszFilename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // shove the image into the dc hbmOldBitMap = (HBITMAP)SelectObject(hdcMemory, hbmNewBitMap); // grab the bitmap's properties BITMAP bmp; GetObject(hbmNewBitMap, sizeof(BITMAP), (LPVOID) &bmp); // grab the width & height iWidth = bmp.bmWidth; iHeight = bmp.bmHeight;}void BitMapObject::Create(HDC hdcCompatible, int width, int height){ // if hdcMemory isn't null, blow it up! if(hdcMemory) Destroy(); // create the memory dc. hdcMemory = CreateCompatibleDC(hdcCompatible); // create the bitmap hbmNewBitMap = CreateCompatibleBitmap(hdcCompatible, width, height); // shove the image into the dc hbmOldBitMap = (HBITMAP)SelectObject(hdcMemory, hbmNewBitMap); // change the width and height. iWidth = width; iHeight = height;}void BitMapObject::Destroy(){ // restore old bitmap SelectObject(hdcMemory, hbmOldBitMap); // delete new bitmap. DeleteObject(hbmNewBitMap); // delete device context. DeleteDC(hdcMemory); //set members to 0/NULL hdcMemory = NULL; hbmNewBitMap = NULL; hbmOldBitMap = NULL; iWidth = 0; iHeight = 0;}BitMapObject::operator HDC(){ //return hdcMemory. return(hdcMemory);}int BitMapObject::GetWidth(){ // return width return(iWidth);}int BitMapObject::GetHeight(){ // return height return(iHeight);}
I'm not going into too much detail about how things work. I went into more detail here on it, though not as much as I could have.
Anyway, you want to know the usage. Ok.
//BitMapObject named SpriteBitMapObject Sprite;//loads the bitmap sprite.bmp in the local directory for easy useSprite.Load(NULL,"sprite.bmp");//paints the image contained in Sprite with a width of 'x' and a height of 'y'BitBlt(0,0,x,y,Sprite,0,0,SRCPAINT);//unloads bitmap in memorySprite.Destroy();//...you won't use it as much but here's an exampleHDC hdc=GetDC(hWindowMain)Sprite.Create(hdc,x,y); //creates a 'blank' sprite of width 'x' and height 'y'ReleaseDC(hWndMain, hdc);
-Greven
I'd say that bitmap class from the book could actually load all kinds of bitmaps, but it forces the bitmapheader_256 on all files, which simply won't work. As soon as there's something stored differently, it'll mix up the header with the bitmap data.
The loader code doesn't take care of all the nice extra thingies which might be inside a valid .bmp file.
I suggest Evil_Greven's class, looks pretty solid to me, and let's Windows handle everything.
The loader code doesn't take care of all the nice extra thingies which might be inside a valid .bmp file.
I suggest Evil_Greven's class, looks pretty solid to me, and let's Windows handle everything.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement