Jump to content
  • Advertisement
Sign in to follow this  
Waaayoff

Problem with creating bitmaps..?

This topic is 2849 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

This code creates an bitmap image, except it doesn't work.. The output image cannot be opened so i'm guessing i'm messing up the formatting.. But i can't figure out where..

Oh and, in the CreateBitmap function, i try to use a void pointer, except i get this error: error C2036: 'const void *' : unknown size
Why am i getting this error? It shows up at line 48:
bmpfile.write((char*)(&Data[i * Width - Width]), Width);

So i'm using a char pointer instead..


#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;

#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;

bool CreateBitmap(LPCSTR Name, int Width, int Height, UINT BitCount, const char* Data)
{
const short padding = 0x0000;

// Figure out how much padding is need per row
int padding_per_row = (4 - ((Width * BitCount / 8) % 4)) % 4;

// Create the Info Header data
BITMAPINFOHEADER info;

info.biSize = 40;
info.biWidth = Width;
info.biHeight = Height;
info.biPlanes = 1;
info.biBitCount = BitCount;
info.biCompression = 0;
info.biSizeImage = sizeof(Data) + sizeof(padding) * padding_per_row * Height;
info.biXPelsPerMeter = 0;
info.biYPelsPerMeter = 0;
info.biClrUsed = 0;
info.biClrImportant = 0;

// Create the File Header data
BITMAPFILEHEADER file;

file.bfType = 0x4D42;
file.bfSize = info.biSizeImage + sizeof(file) + sizeof(info);
file.bfReserved1 = 0;
file.bfReserved2 = 0;
file.bfOffBits = 54;

// Create and fill the .bmp file
ofstream bmpfile(Name, ios::out | ios::binary | ios::trunc);

if (bmpfile.is_open())
{
bmpfile.write((char*)&file, sizeof(file));
bmpfile.write((char*)&info, sizeof(info));

// First send in the pixel data, then the padding
for(int i = Height; i > 0; i--)
{
bmpfile.write((char*)(&Data[i * Width - Width]), Width);

for (int j = 0; j < padding_per_row; j++)
bmpfile.write((char*) &padding, 2);
}

return true;
}

return false;
}

int main()
{
char data [12] =
{
0xFF,0x00,0x00, 0x00,0xFF,0x00,
0x00,0x00,0xFF, 0xFF,0xFF,0xFF
};

if (!CreateBitmap("Image.bmp", 2, 2, 24, data))
cout << "Error" << endl;
}



Share this post


Link to post
Share on other sites
Advertisement
info->biSizeImage = sizeof(Data) + sizeof(padding) * padding_per_row * Height;

should be sizeof(Data) * .... Maybe??

Um, sizeof(Data) is suspicious too.

Share this post


Link to post
Share on other sites
sizeof used on a pointer gives you the size of the pointer, not the size of the data the pointer points to. You can't do pointer arithmetic on a void pointer because void has no size.

Share this post


Link to post
Share on other sites
Why would you need or want or think of using sizeof() here?

The size of the bitmap is the padded width times the height. The padded width is the width plus the amount of padding. The width and height are passed as parameters and you have already calculated the padding at this point.

Share this post


Link to post
Share on other sites
Quote:
You can't do pointer arithmetic on a void pointer because void has no size.

Right. So what can i do? I notice that windows' version of CreateBitmap uses a void pointer...



Sorry, stupid mistake, but in my defence i haven't slept properly in ages ;)
Here's the updated code, reflecting what you all said.. (still not working)


#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;

bool CreateBitmap(LPCSTR Name, int Width, int Height, UINT BitCount, const char* Data)
{
const short padding = 0x0000;

// Figure out how much padding is need per row
int padding_per_row = (4 - ((Width * BitCount / 8) % 4)) % 4;

// Create the Info Header data
BITMAPINFOHEADER info;

info.biSize = 40;
info.biWidth = Width;
info.biHeight = Height;
info.biPlanes = 1;
info.biBitCount = BitCount;
info.biCompression = 0;
info.biSizeImage = (Width + padding_per_row) * Height;
info.biXPelsPerMeter = 0;
info.biYPelsPerMeter = 0;
info.biClrUsed = 0;
info.biClrImportant = 0;

// Create the File Header data
BITMAPFILEHEADER file;

file.bfType = 0x4D42;
file.bfSize = info.biSizeImage + sizeof(file) + sizeof(info);
file.bfReserved1 = 0;
file.bfReserved2 = 0;
file.bfOffBits = 54;

// Create and fill the .bmp file
ofstream bmpfile(Name, ios::out | ios::binary | ios::trunc);

if (bmpfile.is_open())
{
bmpfile.write((char*)&file, sizeof(file));
bmpfile.write((char*)&info, sizeof(info));

// First send in the pixel data, then the padding
for(int i = Height; i > 0; i--)
{
bmpfile.write((char*)(&Data[i * Width - Width]), Width);

for (int j = 0; j < padding_per_row; j++)
bmpfile.write((char*) &padding, 2);
}

return true;
}

return false;
}

int main()
{
char data [12] =
{
0xFF,0x00,0x00, 0x00,0xFF,0x00,
0x00,0x00,0xFF, 0xFF,0xFF,0xFF
};

if (!CreateBitmap("Image.bmp", 2, 2, 24, data))
cout << "Error" << endl;
}



Share this post


Link to post
Share on other sites
Your padding calculation is wrong; the amount of padding you calculate per row is a count of bytes, but your unit of padding is a short. Your unit of padding should be a byte, because it is quite possible to require 1 byte or 3 bytes of padding.

Share this post


Link to post
Share on other sites
Thanks for your help by the way

So i just replace
const short padding = 0x0000;
bmpfile.write((char*) &padding, 2);

with
const char padding = 0x0000;
bmpfile.write(&padding, 1); ?

Still not working.. Ugh!!

Share this post


Link to post
Share on other sites
You could skip the j loop and just have:

char Padding[3]={0,0,0};

bmpfile.write(padding, padding_per_row);

------------

However, there are a number of issues with your code. For a start you tell the bitmap size it is (Width + padding_per_row) * Height;

From MSDN, this member is measured as:

biSizeImage:
The size, in bytes, of the image.

You are passing it the number of pixels, not the number of bytes. (Hint: How many bytes per pixel do you have?)

This issue is repeated:

bmpfile.write((char*)(&Data[i * Width - Width]), Width);

All these 'widths' are assuming one byte per pixel

-----
info.biSize = 40;

Do not use 40. use sizeof(BITMAPINFOHEADER)

------

bfOffBits *may* be from the END of the BITMAPFILEHEADER not the start (I'm not sure)

-----

Regarding the use of void.
If you wish to accept a void * parameter you can then cast into a char *.

bool CreateBitmap(LPCSTR Name, int Width, int Height, UINT BitCount, const void * vpData)
{
cost char * Data=(char *)vpData;
//Now ready for use

However, this may be against convention.

Share this post


Link to post
Share on other sites
I fixed my code. It works for 24-bit formats only..

I can't get it to work with 8 bit!!! The code below is for 24-bit. To use 8-bit bitmaps, i change the width to 6 instead of 2, change the BitCount to 8 instead of 24 and i replace this line:

bmpfile.write((char*)(&Data[i * (Width * 3) - (Width * 3)]), Width * 3);

With:

bmpfile.write((char*)(&Data[i * Width - Width]), Width);

Won't work!! :(


#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;

bool CreateBitmap(LPCSTR Name, int Width, int Height, UINT BitCount, const char* Data, int DataSize)
{
const char padding = 0x0000;

// Figure out how much padding is need per row
int padding_per_row = (4 - ((Width * BitCount / 8) % 4)) % 4;

// Create the Info Header data
BITMAPINFOHEADER info;

info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = Width;
info.biHeight = Height;
info.biPlanes = 1;
info.biBitCount = BitCount;
info.biCompression = 0;
info.biSizeImage = DataSize + (padding_per_row * Height * sizeof(padding));
info.biXPelsPerMeter = 0;
info.biYPelsPerMeter = 0;
info.biClrUsed = 0;
info.biClrImportant = 0;

// Create the File Header data
BITMAPFILEHEADER file;

file.bfType = 0x4d42;
file.bfSize = info.biSizeImage + sizeof(file) + sizeof(info);
file.bfReserved1 = 0;
file.bfReserved2 = 0;
file.bfOffBits = 54;

// Create and fill the .bmp file
ofstream bmpfile(Name, ios::out | ios::binary | ios::trunc);

if (bmpfile.is_open())
{
bmpfile.write((char*)&file, sizeof(file));
bmpfile.write((char*)&info, sizeof(info));

// First send in the pixel data, then the padding
for(int i = Height; i > 0; i--)
{
bmpfile.write((char*)(&Data[i * (Width * 3) - (Width * 3)]), Width * 3);

for (int j = 0; j < padding_per_row; j++)
{
bmpfile.write(&padding, 1);
}
}

return true;
}

return false;
}

int main()
{
char data [6] =
{
0,255,0, 255, 0, 0
};

if (!CreateBitmap("Image.bmp", 2, 1, 24, data, sizeof(data)))
cout << "Error" << endl;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!