bmpsize to small??

I compiled the following code, which produces working bmp's (24bit color;size:1.5 MB), when I take a screenshot and paste it in mspaint, it produces a bmp with size 2.5 MB (also 24 bits color). The bmp's with the compiled code can't be read with certain programs (photoeditor,....).
My question is: how can I adapt my code (without using the libraries from www.smalleranimals.com or sth like this) so that it produces the 2.5 MB screenshots ????

Thanks.
*****


#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>  

int CaptureBMP();


/*void main(int argc,char *argv[])
{
int a=CaptureBMP();
}*/

int main(int argc, char* argv[])
{
int a=CaptureBMP();

      return 0;
}




int CaptureBMP()
{
     // Source[1]
     HDC hdcScr, hdcMem;
     HBITMAP hbmScr;
     BITMAP bmp;
     int iXRes, iYRes;
 
     // Create a normal DC and a memory DC for the entire screen. The
     // normal DC provides a "snapshot" of the screen contents. The
     // memory DC keeps a copy of this "snapshot" in the associated
     // bitmap.
     hdcScr = CreateDC("DISPLAY", NULL, NULL, NULL);
     hdcMem = CreateCompatibleDC(hdcScr);
 
     iXRes = GetDeviceCaps(hdcScr, HORZRES);
     iYRes = GetDeviceCaps(hdcScr, VERTRES);
 
     // Create a compatible bitmap for hdcScreen.
  hbmScr = CreateCompatibleBitmap(hdcScr, iXRes, iYRes);
     if (hbmScr == 0) return 0;
 
     // Select the bitmaps into the compatible DC.
     if (!SelectObject(hdcMem, hbmScr)) return 0;
 
     // Copy color data for the entire display into a
     // bitmap that is selected into a compatible DC.
     if (!StretchBlt(hdcMem,
          0, 0, iXRes, iYRes,
          hdcScr,
          0, 0, iXRes, iYRes,
          SRCCOPY))
 
          return 0;
 
     // Source[2]
     PBITMAPINFO pbmi;
    WORD cClrBits;
 
     // Retrieve the bitmap's color format, width, and height.
     if (!GetObject(hbmScr, sizeof(BITMAP), (LPSTR) &bmp)) return 0;
 
     // Convert the color format to a count of bits.
     cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
     if (cClrBits == 1)
          cClrBits = 1;
     else if (cClrBits <= 4)
          cClrBits = 4;
     else if (cClrBits <= 8)
          cClrBits = 8;
     else if (cClrBits <= 16)
          cClrBits = 16;
     else if (cClrBits <= 24)
          cClrBits = 24;
     else cClrBits = 32;
 
     // Allocate memory for the BITMAPINFO structure. (This structure
     // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
     // data structures.)
     if (cClrBits != 24)
          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                    sizeof(BITMAPINFOHEADER) +
                    sizeof(RGBQUAD) * (1 << cClrBits));
 
     // There is no RGBQUAD array for the 24-bit-per-pixel format.
     else
          pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                    sizeof(BITMAPINFOHEADER));
 
     // Initialize the fields in the BITMAPINFO structure.
     pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     pbmi->bmiHeader.biWidth = bmp.bmWidth;
     pbmi->bmiHeader.biHeight = bmp.bmHeight;
     pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
     pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
     if (cClrBits < 24)
          pbmi->bmiHeader.biClrUsed = (1 << cClrBits);
 
     // If the bitmap is not compressed, set the BI_RGB flag.
     pbmi->bmiHeader.biCompression = BI_RGB;
 
     // Compute the number of bytes in the array of color
     // indices and store the result in biSizeImage.
     pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8
                                   * pbmi->bmiHeader.biHeight * cClrBits;
 
     // Set biClrImportant to 0, indicating that all of the
     // device colors are important.
     pbmi->bmiHeader.biClrImportant = 0;
 
     HANDLE hf;                  // file handle
     BITMAPFILEHEADER hdr;       // bitmap file-header
     PBITMAPINFOHEADER pbih;     // bitmap info-header
     LPBYTE lpBits;              // memory pointer
     DWORD dwTotal;              // total count of bytes
     DWORD cb;                   // incremental count of bytes
     BYTE *hp;                   // byte pointer
     DWORD dwTmp;
 
     pbih = (PBITMAPINFOHEADER) pbmi;
     lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
 
     if (!lpBits) return 0;
 
     // Retrieve the color table (RGBQUAD array) and the bits
     // (array of palette indices) from the DIB.
     if (!GetDIBits(hdcMem, hbmScr, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS)) return 0;
 
     // Create the .BMP file.
     hf = CreateFile("E:\\2.bmp",
                         GENERIC_READ | GENERIC_WRITE,
                         (DWORD) 0,
                         NULL,
                         CREATE_ALWAYS,
                         FILE_ATTRIBUTE_NORMAL,
                         (HANDLE) NULL);
     if (hf == INVALID_HANDLE_VALUE) return 0;
 
     hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"
 
     // Compute the size of the entire file.
     hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
                     pbih->biSize + pbih->biClrUsed *
                     sizeof(RGBQUAD) + pbih->biSizeImage);
     hdr.bfReserved1 = 0;
     hdr.bfReserved2 = 0;
 
     // Compute the offset to the array of color indices.
     hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
                         pbih->biSize + pbih->biClrUsed *
                         sizeof (RGBQUAD);
 
     // Copy the BITMAPFILEHEADER into the .BMP file.
     if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) return 0;
 
     // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
     if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
                    + pbih->biClrUsed * sizeof (RGBQUAD),
                    (LPDWORD) &dwTmp, NULL))
          return 0;
 
     // Copy the array of color indices into the .BMP file.
     dwTotal = cb = pbih->biSizeImage;
     hp = lpBits;
     if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp, NULL)) return 0;
 
     // Close the .BMP file.
     if (!CloseHandle(hf)) return 0;
 
     // Free memory.
     GlobalFree((HGLOBAL)lpBits);
     ReleaseDC(0, hdcScr);
     ReleaseDC(0, hdcMem);
 
     return 1;
}
*****
André123Asked:
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.

ZedFXCommented:
I would advise you to write it to file byte-by-byte. Here is my code for writing bitmaps.

This is how a bitmap is built up

1. The File Header
2. The Info Header
3a. [Optional] The Colour Table
3b. The Bitmap Data

// File header data

member          data type     size in bytes     data it should contain
bfType          short     2          "BM"
bfSize          long     4          File Length (in bytes)
bfReserved1     short     2          two (char 0)
bfReserved2     short     2          two (char 0)
bfOffBits          long     4          File Length - biSizeImage

// Info header data

member          data type     size in bytes     data it should contain
biSize          long     4          sizeof(infoheader)
biWidth          long     4          width of bitmap
biHeight          long     4          height of bitmap
biPlanes          short     2          number of planes (usually 1, unless you are making some hi-tec app)
biBitCount          short     2          number of bits (i will cover using 8 and 24)
biCompression     long     4          0 (unless you are using RLE compression)
biSizeImage     long     4          (Width + 2) * Height (plus 2 for padding)
biXPelsPerMeter     long     4          0 (it is easier to let this be decided automatically, uses standard resolution)
biYPelsPerMeter     long     4          0 (it is easier to let this be decided automatically, uses standard resolution)
biClrUsed          long     4          0 (specifies number of colours used from the table
biClrImportant     long     4          0 (specifies important colours)

that covers the first 54 bytes of the file

// Colour Table [Optional]

if you have an 8 bit bitmap or less then you need a colour table. I shall only tell you about 8 bit bitmaps here because the other types are harder to do.

A colour table specifies the colours you use in your bitmap. In an 8 bit bitmap there will be 256 colours (from 0 to 255)
The next 1024 bytes of the file are the colour table.

format: B,G,R,(char 0) // 4 bytes, 1 colour

// Bitmap Data

In an 8 bit bitmap each pixel of the bitmap will be 1 byte (a reference to the colour table), in a 24 bit bitmap each pixel is 3 bytes (the pure colour).
There are 2 bytes of (char 0) padding following every line of pixels.

eg. imagine a bitmap like so:

red     blue     red
green     green     purple

3 pixels long and 2 pixels high

go along the first row, passing the data, then padding, then the next row

passdata << red
passdata << blue
passdata << red
passdata << (char 0)
passdata << (char 0)
passdata << green
passdata << green
passdata << purple
passdata << (char 0)
passdata << (char 0)

as a 24 bit bitmap it would look something like this:
0  0  255  255  0  0  0  0  255  0  0  0  255  0  0  255  0  255  0  255  0  0

as an 8 bit bitmap it would look somehting like this (assuming colour table where red = 0, blue = 1, green = 2 and purple = 3):
0  1  0  0  0  2  2  3  0  0

i hope there is enough information there for you to do some coding with it becuase it took me ages to come up with that !

(i actually only worked out the code about a week ago for my own uses)

Enjoy ;-)

ZedFX
0

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
ZedFXCommented:
well its not exactly code is it, eesh. I hope it solves your problem tho.
0
RJSoftCommented:
You need to call GetDiBits twice. Once to correctly fill the values in the BITMAPINFOHEADER and another obtain the bits. Then write the file.

In this example I wanted to capture an image and then blur it with a function from a library I purchased. Only thing was it was way too slow.

Have fun!

RJSoft

void Flame::BlurTheFlame(HWND hw,HDC MemDC,HBITMAP hNewBitmap,RECT rr)
{
int WIDE=rr.right-rr.left;
int HIGH=rr.bottom-rr.top;
//
int PaletteColors=(GetDeviceCaps(MemDC,RASTERCAPS) & RC_PALETTE);
//
DWORD Size=sizeof(BITMAPINFOHEADER)+PaletteColors*sizeof(RGBQUAD);
LPBITMAPINFO lpbi=(LPBITMAPINFO)(new char[Size]);
//
BITMAP bmp;::GetObject(hNewBitmap,sizeof(BITMAP),&bmp);
//
lpbi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpbi->bmiHeader.biWidth=bmp.bmWidth;
lpbi->bmiHeader.biHeight=bmp.bmHeight;
lpbi->bmiHeader.biPlanes=bmp.bmPlanes;
lpbi->bmiHeader.biBitCount=bmp.bmPlanes*bmp.bmBitsPixel;
lpbi->bmiHeader.biCompression=BI_RGB;
lpbi->bmiHeader.biSizeImage=0;
lpbi->bmiHeader.biXPelsPerMeter=0;
lpbi->bmiHeader.biYPelsPerMeter=0;
lpbi->bmiHeader.biClrUsed=0;
lpbi->bmiHeader.biClrImportant=0;
//
//Use GetDIBits to Load bi information
int NumberOfScanLines=GetDIBits(
  MemDC,             // handle to device context
  hNewBitmap,        // handle to bitmap
  0,                 // first scan line to set in destination bitmap
  HIGH,              // number of scan lines to copy
  NULL,              // address of array for bitmap bits
  lpbi,              // address of structure with bitmap data
  DIB_RGB_COLORS     // RGB or palette index
);
//
if(NumberOfScanLines==0)
{
::MessageBox(NULL,"GetDiBits Failed 1","ERROR",MB_OK);
delete []lpbi;
return;
}
//
//if (lpbi->bmiHeader.biBitCount <= 1)lpbi->bmiHeader.biBitCount = 1;
//else if (lpbi->bmiHeader.biBitCount <= 4)lpbi->bmiHeader.biBitCount = 4;
//else if (lpbi->bmiHeader.biBitCount <= 8)lpbi->bmiHeader.biBitCount = 8;
//else lpbi->bmiHeader.biBitCount = 24;
//
// Create memory for bits
//
LPVOID lpbvBits = ::GlobalAlloc(GMEM_FIXED,lpbi->bmiHeader.biSizeImage);
//
// Now get actual bits
NumberOfScanLines=GetDIBits(
      MemDC,
      hNewBitmap,
      0,
      HIGH,//lpbi->bmiHeader.biHeight,
      lpbvBits,(LPBITMAPINFO)lpbi,DIB_RGB_COLORS);
if(NumberOfScanLines==0)
{
::MessageBox(NULL,"GetDIBits failed 2","sorry",MB_OK);
delete []lpbi;
::GlobalFree(lpbvBits);
return;
}
//else MessageBox(NULL,"GOOD","GOOD",MB_OK);
//
//reverse the bits for library
char *CharMem = new char[lpbi->bmiHeader.biSize];
::memcpy(CharMem,lpbvBits,lpbi->bmiHeader.biSize);
_strrev( CharMem);//reverse
::memcpy(lpbvBits,CharMem,lpbi->bmiHeader.biSize);
//
delete []CharMem;
//
Image Im;
//const unsigned int WW=rr.right-rr.left;
//const unsigned int HH=rr.bottom-rr.top;
Im.read(WIDE,HIGH,"RGB",CharPixel,lpbvBits);
Im.blur(1,2);
//
delete []lpbi;
::GlobalFree(lpbvBits);

}//endfunc
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

André123Author Commented:
thanks, but it didn't worked.
Do you happen to know how I should adapt the code so that the produced bmp is an 8-bits-colordepth bitmap??
0
ZedFXCommented:
Look at the notes ive written ^^
0
RJSoftCommented:
Also I should have removed the reverse string thing in the code as it was specific to the library. In short dont reverse.

As for your question of how to make an 8 bit color depth just set the biBitCount to 8.

//if (lpbi->bmiHeader.biBitCount <= 1)lpbi->bmiHeader.biBitCount = 1;
//else if (lpbi->bmiHeader.biBitCount <= 4)lpbi->bmiHeader.biBitCount = 4;
//else if (lpbi->bmiHeader.biBitCount <= 8)lpbi->bmiHeader.biBitCount = 8;
//else lpbi->bmiHeader.biBitCount = 24;


RJ
0
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
C++

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.