简体   繁体   中英

Taking screenshots

I have a problem with taking screenshots. Everything is fine, but I have a problem with it in resolution 1366x768. Bitmap is broken and I can't open this file.

HDC _dc = GetWindowDC(okno); 
Szer_Wys(); //ustawia szerokosc i wysokosc aktywnego ekranu

dc = CreateCompatibleDC( 0 );
bm = CreateCompatibleBitmap( _dc, w, h );
SelectObject( dc, bm );
StretchBlt( dc, 0, 0, w, h, _dc, 0, 0, w, h, SRCCOPY );

GetObject( bm, 84, buf );
ddd = GetDC( 0 );
dc2 = CreateCompatibleDC( ddd );

tagBITMAPINFO bit_info; //tworzy obiekt na strukture 
bit_info.bmiHeader.biSize = sizeof( bit_info.bmiHeader );  //Rozmiar struktury bmiHeader (40 )
bit_info.bmiHeader.biWidth = w; //Szerokość bitmapy w pikselac
bit_info.bmiHeader.biHeight = h;  //wysokosc bitmapy w pikselac
bit_info.bmiHeader.biPlanes = 1;  
bit_info.bmiHeader.biBitCount = 24; //Liczba bitów kodujących piksel (RGB)
bit_info.bmiHeader.biCompression = 0; //0 - brak wewnętrznej kompresji
bit_info.bmiHeader.biSizeImage = 0; 

h_createDIB = CreateDIBSection( dc, & bit_info, DIB_RGB_COLORS, & buf, 0, 0 );                
GetDIBits( dc, bm, 0, h, buf, & bit_info, DIB_RGB_COLORS );


BITMAPFILEHEADER bit_header;
bit_header.bfType = MAKEWORD( 'B', 'M' ); //typ pliku
bit_header.bfSize = w * h * 3 + 54; //w * h * 3 kolory + nagłówek 
bit_header.bfOffBits = 54;

BITMAPINFOHEADER bit_info_header;
bit_info_header.biSize = 40;
bit_info_header.biWidth = w;
bit_info_header.biHeight = h;
bit_info_header.biPlanes = 0;
bit_info_header.biBitCount = 24;
bit_info_header.biCompression = 0;
bit_info_header.biSizeImage = w * h * 3;


sciezka = obiekt.PobierzPathSCREEN() +  obiekt.PobierzNazwe() + ".bmp";        
ofstream plik(sciezka, ios::binary);
if(plik.good())
{
        plik.write(reinterpret_cast<char*>(&bit_header), sizeof(bit_header));
        plik.write(reinterpret_cast<char*>(&bit_info_header), sizeof(bit_info_header));
        plik.write(reinterpret_cast<char*>(buf), w*h*3 );

}else cout<<"Blad pliku";

plik.close();

*Szer_Wys()* is reading screen resolution.

EDIT

I changed the content of Szer_Wys() to this:

void Zrzut::Szer_Wys()
{
    RECT re;
    GetWindowRect( okno, & re );
    w = re.right, h = re.bottom;

    while(w%4 != 0)
    {
            w++;
    }
}

And now everything works fine :)

Try the following:-

  1. Use MSPaint (or whatever) and create a 1366x768 image.
  2. Make image pure red
  3. Save as BMP
  4. Modify your code to fill the bitmap with red instead of copying the screen
  5. Run your code
  6. Compare the two files, the one created by MSPaint and the one your code created

The count of bytes per line in a Bitmap must be a multiple of 4. In your case it is

(3*1366)/4=1024,5 not a multiple of 4

you have to save it line by line, with padding it with two bytes each line. Keep in mind that this change the biSizeImage and bfSize member but not the width and height of the image. You can avoid that problem if you use 32bit per pixel.

You are missing the fact that scanlines need to be DWORD aligned (padded to next 32-bit alignment boundary).

The scan lines are DWORD aligned, except for RLE-compressed bitmaps. They must be padded for scan line widths, in bytes, that are not evenly divisible by four, except for RLE compressed bitmaps. For example, a 10- by 10-pixel 24-bpp bitmap will have two padding bytes at the end of each scan line.

So, each scan line will be ((w * 3) + 3) & ~3 bytes and then you multiply this by h to get image size. Without this padding the image is broken.

You can also leverage macros provided with Windows SDK, amvideo.h (and they also explain the format once again):

// DIBSIZE calculates the number of bytes required by an image

#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
#define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount)
#define _DIBSIZE(bi) (DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight)
#define DIBSIZE(bi) ((bi).biHeight < 0 ? (-1)*(_DIBSIZE(bi)) : _DIBSIZE(bi))

To add to this, when you are writing to file, you once again initialize the structure bit_info_header and you put different values there for no reason. For instance, you put zero planes there, while the number of planes has to be set to 1 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM