Skip to content

Commit

Permalink
win32: rewrite screenshot code (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
darealshinji authored and woodruffw committed Aug 27, 2016
1 parent f0a37e7 commit e5a02a0
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 212 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ diantahoc
NachoSimo
nyanpasu
Aaron Caffrey (wifiextender)
djcj <[email protected]> (a.k.a. darealshinji on Github)
50 changes: 0 additions & 50 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



Microsoft Limited Public License

This license governs use of code marked as "sample" or "example" available on
this web site without a license agreement, as provided under the section above
titled "NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE." If you use
such code (the "software"), you accept this license. If you do not accept the
license, do not use the software.

1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution"
have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.

2. Grant of Rights
(A) Copyright Grant - Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a non-exclusive,
worldwide, royalty-free copyright license to reproduce its contribution, prepare
derivative works of its contribution, and distribute its contribution or any derivative
works that you create.
(B) Patent Grant - Subject to the terms of this license, including the license conditions
and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
royalty-free license under its licensed patents to make, have made, use, sell, offer
for sale, import, and/or otherwise dispose of its contribution in the software or
derivative works of the contribution in the software.

3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors'
name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim
are infringed by the software, your patent license from such contributor to the
software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright,
patent, trademark, and attribution notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do
so only under this license by including a complete copy of this license with your
distribution. If you distribute any portion of the software in compiled or object
code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors
give no express warranties, guarantees or conditions. You may have additional
consumer rights under your local laws which this license cannot change. To the
extent permitted under your local laws, the contributors exclude the implied
warranties of merchantability, fitness for a particular purpose and non-infringement.
(F) Platform Limitation - The licenses granted in sections 2(A) and 2(B) extend
only to the software or derivative works that you create that run on a Microsoft
Windows operating system product.
205 changes: 56 additions & 149 deletions src/plat/win32/bitmap.c
Original file line number Diff line number Diff line change
@@ -1,191 +1,98 @@
/* bitmap.c
/* bitmap.c
** Author: djcj <[email protected]>
** -------------
**
** Copyright (c) 2016 Microsoft
** Source: https://msdn.microsoft.com/de-de/library/windows/desktop/dd145119(v=vs.85).aspx
**
** The bitmap saving functions used by screenfetch-c on Windows are implemented here.
**
** According to section 2b of the Microsoft Developer Services Agreement
** this code is released under the Microsoft Limited Public License.
**
** Usage:
** HBITMAP hBitmap;
** HDC hdc;
** PBITMAPINFO pBitmapInfo = createBitmapInfoStruct(hBitmap);
** createBmpFile("picture.bmp"), pBitmapInfo, hBitmap, hdc);
** The screenshot functions used by screenfetch-c on Windows are implemented here.
** Like the rest of screenfetch-c, this file is licensed under the MIT license.
*/

#include <Windows.h>

PBITMAPINFO createBitmapInfoStruct(HBITMAP hBmp)
int createBitmapFile(LPCTSTR lpszFileName, HBITMAP hBitmap, HDC hdc)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
/* retrieve the bitmap color format, width, and height */
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
{
return NULL;
}
BITMAP bitmap;
BITMAPFILEHEADER bitmapFileHeader;

/* 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
if (!GetObject(hBitmap, sizeof(BITMAP), &bitmap))
{
cClrBits = 32;
return -1;
}

/* 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));
}
else
{
/* there is no RGBQUAD array for the 24-bit-per-pixel format */
pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
}
int infoHeaderSize = sizeof(BITMAPINFOHEADER);
int rgbQuadSize = sizeof(RGBQUAD);
int bits = bitmap.bmPlanes * bitmap.bmBitsPixel;
int infoHeaderSizeImage = ((bitmap.bmWidth * bits + 31) &~31) / 8 *
bitmap.bmHeight;

/* 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);
}
PBITMAPINFO pBitmapInfo = (PBITMAPINFO) LocalAlloc(LPTR,
infoHeaderSize + rgbQuadSize * (1 << bits));

/* 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.
For Windows NT, the width must be DWORD aligned unless
the bitmap is RLE compressed. This example shows this.
For Windows 95/98/Me, the width must be WORD aligned unless the
bitmap is RLE compressed.
*/
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits + 31) & ~31) / 8
* pbmi->bmiHeader.biHeight;

/* set biClrImportant to 0, indicating that all of the
device colors are important
*/
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
pBitmapInfo->bmiHeader.biSize = infoHeaderSize;
pBitmapInfo->bmiHeader.biBitCount = bitmap.bmBitsPixel;
pBitmapInfo->bmiHeader.biClrImportant = 0;
pBitmapInfo->bmiHeader.biClrUsed = 0;
pBitmapInfo->bmiHeader.biCompression = BI_RGB;
pBitmapInfo->bmiHeader.biHeight = bitmap.bmHeight;
pBitmapInfo->bmiHeader.biWidth = bitmap.bmWidth;
pBitmapInfo->bmiHeader.biPlanes = bitmap.bmPlanes;
pBitmapInfo->bmiHeader.biSizeImage = infoHeaderSizeImage;

int createBmpFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
{
HANDLE hf; /* file handle */
BITMAPFILEHEADER hdr; /* bitmap file-header */
PBITMAPINFOHEADER pbih; /* bitmap info-header */
LPBYTE lpBits; /* memory pointer */
DWORD cb; /* incremental count of bytes */
BYTE *hp; /* byte pointer */
DWORD dwTmp;

pbih = (PBITMAPINFOHEADER)pbi;
lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

if (!lpBits)
PBITMAPINFOHEADER pBitmapInfoHeader = (PBITMAPINFOHEADER) pBitmapInfo;
LPBYTE mem = GlobalAlloc(GMEM_FIXED, pBitmapInfoHeader->biSizeImage);

if (!mem)
{
return -1;
}

/* retrieve the color table (RGBQUAD array) and the bits
(array of palette indices) from the DIB
*/
if (!GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight, lpBits,
pbi, DIB_RGB_COLORS))
if (!GetDIBits(hdc, hBitmap, 0, pBitmapInfoHeader->biHeight, mem, pBitmapInfo,
DIB_RGB_COLORS))
{
return -1;
}

/* create the .BMP file */
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD)0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
if (hf == INVALID_HANDLE_VALUE)
int fileHeaderSize = sizeof(BITMAPFILEHEADER);
int fileAndInfoHeaderSize = fileHeaderSize + infoHeaderSize +
pBitmapInfoHeader->biClrUsed * rgbQuadSize;

bitmapFileHeader.bfType = 'B' + ('M' << 8);
bitmapFileHeader.bfOffBits = fileAndInfoHeaderSize;
bitmapFileHeader.bfSize = fileAndInfoHeaderSize + pBitmapInfoHeader->biSizeImage;
bitmapFileHeader.bfReserved1 = 0;
bitmapFileHeader.bfReserved2 = 0;

HANDLE handleFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (handleFile == INVALID_HANDLE_VALUE)
{
return -1;
}
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))

long unsigned int dwWritten = 0;

if (!WriteFile(handleFile, &bitmapFileHeader, fileHeaderSize, &dwWritten, NULL))
{
return -1;
}

/* copy the BITMAPINFOHEADER and RGBQUAD array into the file */
if (!WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof(RGBQUAD),
(LPDWORD)&dwTmp, (NULL)))
if (!WriteFile(handleFile, pBitmapInfoHeader,
infoHeaderSize + pBitmapInfoHeader->biClrUsed * rgbQuadSize, &dwWritten,
NULL))
{
return -1;
}

/* copy the array of color indices into the .BMP file */
cb = pbih->biSizeImage;
hp = lpBits;
if (!WriteFile(hf, (LPSTR)hp, (int)cb, (LPDWORD)&dwTmp, NULL))
if (!WriteFile(handleFile, mem, pBitmapInfoHeader->biSizeImage, &dwWritten, NULL))
{
return -1;
}

/* close the .BMP file */
if (!CloseHandle(hf))
if (!CloseHandle(handleFile))
{
return -1;
}

/* free memory */
GlobalFree((HGLOBAL)lpBits);

GlobalFree(mem);
return 0;
}
16 changes: 6 additions & 10 deletions src/plat/win32/bitmap.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
/* bitmap.h
/* bitmap.h
** Author: djcj <[email protected]>
** -------------
**
** Copyright (c) 2016 Microsoft
** Source: https://msdn.microsoft.com/de-de/library/windows/desktop/dd145119(v=vs.85).aspx
**
** Function prototypes for bitmap.c.
**
** According to section 2b of the Microsoft Developer Services Agreement
** this code is released under the Microsoft Limited Public License.
** Function prototypes for bitmap.c.
** Like the rest of screenfetch-c, this file is licensed under the MIT license.
*/

#ifndef SCREENFETCH_C_BITMAP_H
#define SCREENFETCH_C_BITMAP_H

#include <Windows.h>

PBITMAPINFO createBitmapInfoStruct(HBITMAP hBmp);
int createBmpFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
int createBitmapFile(LPCTSTR lpszFileName, HBITMAP hBitmap, HDC hdc);

#endif /* SCREENFETCH_C_BITMAP_H */
4 changes: 1 addition & 3 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ void take_screenshot(bool verbose)
BitBlt(mem_dc, 0, 0, horiz, vert, screen_dc, 0, 0, SRCCOPY);
bitmap = SelectObject(mem_dc, old_bitmap);

PBITMAPINFO pBitmapInfo = createBitmapInfoStruct(bitmap);

if (createBmpFile("screenfetch_screenshot.bmp", pBitmapInfo, bitmap, mem_dc) == 0)
if (createBitmapFile("screenfetch_screenshot.bmp", bitmap, mem_dc) == 0)
{
VERBOSE_OUT("Screenshot successfully saved.", "");
}
Expand Down

0 comments on commit e5a02a0

Please sign in to comment.