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:-
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.