BMP Images

I have two dimensional array of 8 bit values of dimensions 512 x 512 which stores the pixel information of a 8 bit monochrome image.

I need to do two things with this data, firstly I need to display it on screen as an image and secondly I need to save it to disk as a BMP image (so similar standard).

Many thanks,

Alex Baskeyfield
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

That is OS-specific.  What OS?
For windows this can get very complicated.   You woudl really need to learn windows programming, which is well beyond the scope of a single question.  There are whole books (1000s of them) on the subject.

But here is some annotated code used to display a bitmap in windows.  I suspect it won't make any sense to you at all.  You woudl have to learn a lot first.

You can copy a bitmap, or a portion of a bitmap between two compaible DC's using BitBlt.  So to copy a bitmap to the screen you need to create a DC that is compatible with the screen and copy the source bitmap from it to the screen.

First you need to have a Source DC, this is a memory DC for the source bitmap, that is the image to be copied to the display.  This DC must be compatible with the source bitmap and (since the source bitmap is compatible with the display) also compatible with the display.  You can use

HDC SrcDC = CreateCompatibleDC(DspDC);

to create a memory DC (SrcDC) that is compatible with the display DC (DspDC).  (The display DC may be a window's DC or a DC for the screen (display) obtaned with CreateDC().)

Next you need to select the source bitmap into the source DC.  Now this works like selecting any other tool, you must save the previous tool so you can select it back in before the DC is returned to the OS.  So you would do

HBITMAP OldSrcBmp = SelectObject(SrcDC,SrcBmp);

Now the memory DC contains the bitmap to be copied.  You can copy the source DC's image to the destination DC using BitBlt().

Next you need to clean up.  You do this by selecting the original bitmap back into the memory DC and then deleting the DC.  Like


Let me know if you have any questions.

When it comes to creating the bitmap   I think your best bet is to use CreateDIBSection  (Again this is for windows only).  This will create a bitmap whose memory you can "write" to directly.   so you could then use memcopy() or a similar operation to copy your bitmal data to this bitmap.

I hope this helps some.   I think you've got a lot to learn.   (And you'll need to create a windows program in order to have a window in which to display it....)
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

It's easy on Borland :)

// array = the 2D data, width x height
HPALLETE CreateBWPallete()
   TLogPallete* pal;
   HPALETTE hpal;
   int i;

    pal = malloc(sizeof(TLogPalette) + sizeof(TPaletteEntry) * 256);
    pal->palVersion := 0x300;
    pal->palNumEntries := 256;
    for(i=0; i<=255; i++) {
      pal->palPalEntry[i].peRed := i;
      pal->palPalEntry[i].peGreen := i;
      pal->palPalEntry[i].peBlue := i;
    hpal := CreatePalette(pal);
    return hpal;

ConvertAndSave(char *array, int width, int height, char *fname)
    int x,y;
    unsigned char *p;
    TBitmap* bitmap;

    bitMap = new TBitMap();
    bitmap->PixelFormat := pf8bit;
    bitmap->Height = height;
    bitmap->Width = width;
    for (y = 0; y<height; y++) {
      p = bitmap->ScanLine(y);
      for (x = 0; x<width; x++) {
        *p := array++; p++;
    // change the pallete
    bitmap->Pallete = CreateBWPallete();
    // save to file

    // free the bitmap

Note: I converted my Delphi source code for this. The VCL objects is the same, but I can't guarentee it.
Please crosscheck it with the BCB's help.


I don't think that word means what you think it means -- The Princess bride
I would believe your best bet is to learn the BMP format and then simply write the data to a BMP file. If you want to display it you can then either display the BMP data from memory or you can tell windows to open the BMP file and display it.

In either case, the displaying is system specific.

The creation of the BMP file is just making a file and as such isn't system specific at all - you can easily write a utility that creates bmp files on unix. If you want to dispaly them you probably have to take them to a windows machine first but that's a different story.

The short story of the bmp format is this:

The .bmp file has first a BMP file header immediately followed by a BMP header immediately followed by a palette if the file format uses palette immediately followed by image data. If the file has no palette the image data will be just after the BMP header.

The BMP file header and BMP header is defined in Win32 and inspecting any help file on Win32 or include file in windows will show you what those headers look like. They are fixed size records. On other machines you must make sure you pick the right sizes for the fields and also that you get correct padding etc.

The headers will have info about the size of the image in height and width (number of lines and number of pixels per line) as well as how many bits per pixel. Bits per pixel can only take the values 8, 24 and 32. Palette is only used for the 8 bit per pixel version while the 24 and 32 do not use palette. There's no specific entry saying if you use palette or not, it is the bits per pixel value that implicitely indicates the presence or absence of the palette. If you use palette it is also important to know how many colors are present and so there's a field for that too. If you don't use palette such info are rather useless and that member is not defined for formats without palette.

So, there are the following important info stored in the headers that are required to interpret the rest of the image properly:

W = width == number of pixels per line.
H = height == number of lines of the image.
C = number of colors (only defined if palette is used).
bpp == bits per pixel == 8, 24 or 32.

There is also the important info indicating size of palette entry. I am not sure if that size is fixed and is always 32 bits or if the size can be either 24 or 32. If it can vary I am sure the header have a member giving the size.

The size of the headers are fixed. THe offset for the file header is at offset 0. The BMP header is at offset immediately after the file header and so has offset: sizeof(file_header)

The palette if present has offset sizeof(file_header) + sizeof(bmp_header).

The image data has offset equal to sizeof(file_header) + sizeof(bmp_header) + sizeof(palette_entry) * C.

If palette is not used C == 0 and so the image data start immediately after the bmp_header.

IF palette is used there is some extra padding between the end of the palette and the beginning of the image data. The point is that image data always start at an offset that is a multiple of 4. So if you get an offset like 503 from the above then the image data start at 504 and there's a byte of padding.

To add padding to a value to make it divisible by 4 you can use this formula:

off = (off + 3) & ~3;

I believe the headers also have this offset to the image data stored directly in the header so you don't have to compute it.

sizeof(palette_entry) == 3 if the palette entry is 24 bits (RGB) and 4 if the palette entry has 32 bits (RGBA).

The image data is an array of line data. There's one line data for each line so the image data is simply an array of H line_data objects.

The line data is an array of pixel data followed by padding so that the size of line_data is always a multiple of 4. Each line_data always start at an offset in the file that is a multiple of 4. Each line is padded with 0-3 bytes to ensure that the next line comes at a 4 byte boundary.

I don't remember right now if the lines are stored top down or bottom up, but that is easy enough to fix if you get it wrong so I wouldn't worry too much about that.

The line data is then just an array of W pixel data entries, read from left to right. so the left most pixel is stored in the first entry and the right most pixel is stored in the last entry (the one with higher offset).

Each pixel data is either 1 byte (if 8 bit per pixel using palette) or 3 bytes (if 24 bits per pixel using RGB) or 4 bytes (if 32 bits per pixel using RGBA).

In your case you will most likely just store each pixel byte as one byte of pixel data. So you can probably just do a memcpy() to copy the original pixel data to the bmp line_data. If your original format also have such padding between lines you can even just do a raw copy of the whole image:

memcpy(bmp_image_data_ptr,raw_image_ptr,line_size * H);

where line_size is:

line_size = (W + 3) & ~3; // if bits per pixel is 8.
line_size = (3*W + 3) & ~3; // if bits per pixel is 24
line_size = 4*W; // if bits per pixel is 32.

The palette must be set to the greyscale tones, for an 8 bit grey scale image the obvious setting is:

palette index x is set to the value R=x, G=x, B=x.
A if present is set to 0.
The palette is also just a simple array of palette entries. The palette entry is either RGB for a 24 bit palette entry size or RGBA for a 32 bit palette entry size.

The A is the "alpha channel" or transparency.

A = 0 means opaque, the pixel's value is the value of the destination pixel displayed.

A = 255 means transparent, the pixel's RGB value is ignored and the underlying pixel is shown through.

Any value between those two extremes menas that the displayed pixel's RGB value is a mix of the pixel's RGB value and the underlying RGB value.

In your case I assume you want a non-transparent image so you set the A value to 0 if it is present.

Hope this is of help.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
>> The creation of the BMP file is just making a file and as such isn't
>> system specific at all
Yes and no.  It still depends on what OS the bitmap file is for.  Mac bitmaps are definitely different than Windows, for example.   And dislaying the bitmap is very OS-specific.
Well, with BMP file I meant the specific Windows BMP file format. I am not familiar with any MAC BMP format.

However, it is not system specific in the sense that the format is well documented and if you can read/write bytes on a machine you can produce a BMP file on that system. You can convert GIF, JPG etc images to BMP format and you can convert BMP format to other such image formats.

If you want to DISPLAY the image it is of course system specific in that you have to use a system that support displaying such images - as far as I know only windows and similar PC systems does that (OS/2 etc).

However, you can still display it indirectly if you can convert it to GIF or JPEG and display that file, but then you have changed the format and it isn't a BMP file anymore.

Giveing Salte a C for that seems a bit unfair!   It may not answer all your questions completely, but it wasn't intended to either.  You'ved asked a very very big question (one that involves some intensive programming and a lot of study), you aren't going to get a complete, detailed answer from a single expert.   If you are not satisfied with what experts have posted, you can ask additional questions to understand soecific portions of such a large answer.  
Alex_BaskeyfieldAuthor Commented:

My appologies for giving you a grade C, I thought that I gave you a grade A as I found your answer very helpful and am currently using your advice. again, my appologies
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Graphics Software

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.