Bitmap problem

Started by
6 comments, last by Qoy 23 years, 11 months ago
I am having a problem with my bitmap loading and drawing functions. I wanted to ask first, to see if anyone has had the same problem, but if it''s too undescriptive, I''ll post code (or a link to code) and maybe some pictures tomorrow. The problem is that when the bitmap file is of certain dimensions (not the rect I''m drawing, but the whole file) the output is skewed. As in, it slants to the right on the top. When I change the dimensions to certain dimensions, the file is not skewed. I''m loading a 24 bit file and converting it to 16 bit for drawing. I know I''m not being very specific, but before I take the time to write a specific post, I wanted to see if maybe anyone else has had this problem, and knows about it. If nobody responds in like a day or so, I''ll post another, more specific post with code. Thank! ------------------------------ Jonathan Little invader@hushmail.com http://www.crosswinds.net/~uselessknowledge
Advertisement
Have you checked both the picture''s and primary/back- buffers lPitch ??

Sometimes the pitch are not the same as the width.

/maq
- maq
The picture''s pitch could be different from the width?? I don''t know if that would make any difference anyway, though. As it happens, I''m always drawing from a RECT in the source picture.

And as far as I know, the picture''s width is always the picture''s width. It''s also stored in a single dimensional array..

But yes I check the backbuffer. When one of the picture''s is the wrong size, and is drawn skewed, the others still draw correctly, so it''s something that only effects certain widths of bitmaps.
Do you take care of the extra bytes after each line in the bmp file? After each horizontal line bmp puts in a couple of empty bytes to make it dividable by four... I know most numbers are dividable by four but I hope you see what I mean...


Edited by - Geradian on 5/1/00 3:52:47 AM
I was unaware that the format put extra bytes at the end.. I think this could describe the problem, but where can I find more info on this?
We saw the same thing here by looking at the data through a hex editor.

"... you act as if stupidity were a virtue."
-- Flight of the Phoenix
"If you build it, it will crash."

It''s called zero padding and many image formats do it. You have to
calculate the correct number of bytes for a single scanline of the bitmap.
If I had a 32x32 pixel 24-bit bitmap, a single scanline would be 32*3 = 96 bytes.
If I had a 31x31 pixel 24-bit bitmap, you would probably incorrectly
calculate it as 31*3 = 93 bytes. This is wrong. It is really 96 bytes.

But, what''s the purpose of loading this bitmap anyway? Does it have to do
with DirectX and surfaces? If so, just forget about doing it yourself and
use the function DDLoadBitmap from ddutil.cpp. It will load a bitmap onto
a DD surface. It will do the loading and conversion for you.

IDirectDrawSurface7* DDLoadBitmap( IDirectDraw7* pdd, LPCSTR szBitmap, int dx, int dy){    HBITMAP                 hbm;    BITMAP                  bm;    DDSURFACEDESC2          ddsd;    IDirectDrawSurface7    *pdds;    //    //  Try to load the bitmap as a resource, if that fails, try it as a file    //    hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx,                              dy, LR_CREATEDIBSECTION);    if (hbm == NULL)        hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy,                                  LR_LOADFROMFILE / LR_CREATEDIBSECTION);    if (hbm == NULL)        return NULL;    //    // Get size of the bitmap    //    GetObject(hbm, sizeof(bm), &bm);    //    // Create a DirectDrawSurface for this bitmap    //    ZeroMemory(&ddsd, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd);    ddsd.dwFlags = DDSD_CAPS / DDSD_HEIGHT / DDSD_WIDTH;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;    ddsd.dwWidth = bm.bmWidth;    ddsd.dwHeight = bm.bmHeight;    if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)        return NULL;    DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);    DeleteObject(hbm);    return pdds;}HRESULTDDCopyBitmap(IDirectDrawSurface7* pdds, HBITMAP hbm, int x, int y,             int dx, int dy){    HDC                     hdcImage;    HDC                     hdc;    BITMAP                  bm;    DDSURFACEDESC2          ddsd;    HRESULT                 hr;    if (hbm == NULL // pdds == NULL)        return E_FAIL;    //    // Make sure this surface is restored.    //    pdds->Restore();    //    // Select bitmap into a memoryDC so we can use it.    //    hdcImage = CreateCompatibleDC(NULL);    if (!hdcImage)        OutputDebugString("createcompatible dc failed\n");    SelectObject(hdcImage, hbm);    //    // Get size of the bitmap    //    GetObject(hbm, sizeof(bm), &bm);    dx = dx == 0 ? bm.bmWidth : dx;     // Use the passed size, unless zero    dy = dy == 0 ? bm.bmHeight : dy;    //    // Get size of surface.    //    ddsd.dwSize = sizeof(ddsd);    ddsd.dwFlags = DDSD_HEIGHT / DDSD_WIDTH;    pdds->GetSurfaceDesc(&ddsd);    if ((hr = pdds->GetDC(&hdc)) == DD_OK)    {        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,                   dx, dy, SRCCOPY);        pdds->ReleaseDC(hdc);    }    DeleteDC(hdcImage);    return hr;} 

Here is a part of my reading routine. It supposes that the file has already been read into
memory. I am currently only supporting 1 bit and 24 bit modes. Mainly because I can''t manage
to create a bmp file in 32 bit and 16 bit . Why I don''t have 8 bit is because I am lazy!

HRESULT clsSurface::ReadBMPFromMemory(char *Offset)
{
HRESULT hr;
LPBITMAPFILEHEADER BMPFileHeader;
LPBITMAPINFOHEADER BMPInfoHeader;
clsColor Color;
clsColor Palette[255]; //Used when reading in palette. Max is 256 entries.
int X,
Y,
Mod,
Mod2; //Sometime I need two mods...
unsigned char Counter;

//Get the file header.
BMPFileHeader = (LPBITMAPFILEHEADER) Offset;

//Check so this is a window bitmap.
if(BMPFileHeader->bfType != 19778)
return -1;

//Get the info header.
BMPInfoHeader = (LPBITMAPINFOHEADER) (Offset + 14);

//Make sure this size is a windows bitmap.
if(BMPInfoHeader->biSize != 40)
return -1;

//Make sure it ain''t compressed.
if(BMPInfoHeader->biCompression != 0)
return -1;

//Create the surface.
hr = Create(BMPInfoHeader->biWidth, BMPInfoHeader->biHeight);
if FAILED(hr)
return hr;

//Check the bit depth.
switch(BMPInfoHeader->biBitCount)
{
case 1:
//Read in the palette.
for(Counter = 0; Counter < BMPInfoHeader->biClrUsed; Counter++)
{
Palette[Counter].Blue = (int) *(Offset + 54 + (Counter * 4) );
Palette[Counter].Green = (int) *(Offset + 54 + (Counter * 4) + 1);
Palette[Counter].Red = (int) *(Offset + 54 + (Counter * 4) + 2);
}

//Run through all pixels.
Offset += BMPFileHeader->bfOffBits;
Mod = Width % 8;
Mod2 = ((Mod + Width) / 8) % 4;
for(Y = Height - 1; Y >= 0; Y--)
{
for(X = 0; X < Width
{
Counter = 128;
//Run through each byte in this line
do
{
if( (* (Offset + X/8) ) & Counter )
Color.Color = 1;
else
Color.Color = 0;

Color.Red = Palette[ Color.Color ].Red;
Color.Green = Palette[ Color.Color ].Green;
Color.Blue = Palette[ Color.Color ].Blue;
DrawPixel(X, Y, Color);
X++;

if(Counter == 1)
Counter = 0;
else
Counter -= (Counter/2);
} while(Counter > 0);
}
Offset += ((Width + Mod)/8) + Mod2;
}

break;
case 16:
break;
case 24:
Mod = Width % 4;
Offset += BMPFileHeader->bfOffBits ;

//Run through all the pixels.
for(Y = Height - 1; Y >= 0; Y--)
{
for(X = 0; X < Width; X++)
{
//Extract the red, green and blue component.
Color.Red = (char) *Offset;
Color.Green = (char) *(Offset + 1);
Color.Blue = (char) *(Offset + 2);

hr = DrawPixel(X, Y, Color);
if FAILED(hr)
return hr;

Offset += 3;
}
Offset += Mod;
}

break;
case 32:
break;
}

return 0;
}

This topic is closed to new replies.

Advertisement