Skip to content

Commit

Permalink
win32: save screenshots to .bmp file (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
darealshinji authored and woodruffw committed Aug 20, 2016
1 parent fd4086b commit f0a37e7
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ bin/
#ignore objects
*.o
#ignore other binaries created by make
*.exe
screenfetch-c
x11test
gltest
Expand Down
52 changes: 51 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,54 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.
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.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ OLDTARGETS = linux win bsd osx sun
ifeq ($(OS),Windows_NT)
SOURCES += $(wildcard ./src/plat/win32/*.c)
CPPFLAGS += -DWIN32_LEAN_AND_MEAN
LDFLAGS += -lgdi32
else
UNAME_S := $(shell uname -s)

Expand Down
191 changes: 191 additions & 0 deletions src/plat/win32/bitmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/* bitmap.c
**
** 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);
*/

#include <Windows.h>

PBITMAPINFO createBitmapInfoStruct(HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
/* retrieve the bitmap color format, width, and height */
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
{
return NULL;
}

/* 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));
}
else
{
/* there is no RGBQUAD array for the 24-bit-per-pixel format */
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.
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;
}

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)
{
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))
{
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)
{
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))
{
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)))
{
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))
{
return -1;
}

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

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

return 0;
}
20 changes: 20 additions & 0 deletions src/plat/win32/bitmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* bitmap.h
**
** 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.
*/

#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);

#endif /* SCREENFETCH_C_BITMAP_H */
29 changes: 17 additions & 12 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
#include "misc.h"
#include "error_flag.h"

#if defined(__CYGWIN__)
#if defined(__CYGWIN__) || defined(__MSYS__)
#include <Windows.h>
#include "plat/win32/bitmap.h"
#endif

/* safe_strncpy
Expand Down Expand Up @@ -57,7 +58,7 @@ void split_uptime(long uptime, unsigned int *secs, unsigned int *mins,
*/
void take_screenshot(bool verbose)
{
#if !defined(__CYGWIN__)
#if !defined(__CYGWIN__) && !defined(__MSYS__)
int call_status = 1;
char file_loc[MAX_STRLEN];
#endif
Expand All @@ -73,14 +74,7 @@ void take_screenshot(bool verbose)
sleep(1);
printf("%s\n", "0");

#if defined(__CYGWIN__)
/* terrible hack, the printscreen key is simulated */
keybd_event(VK_SNAPSHOT, 0, 0, 0);

if (verbose)
VERBOSE_OUT("Screenshot has been saved to the clipboard.", "");

/* NOT FINSISHED - HBITMAP needs to be saved
#if defined(__CYGWIN__) || defined(__MSYS__)
HDC screen_dc = GetDC(NULL);
HDC mem_dc = CreateCompatibleDC(screen_dc);

Expand All @@ -93,16 +87,27 @@ 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)
{
VERBOSE_OUT("Screenshot successfully saved.", "");
}
else
{
ERR_REPORT("Problem saving screenshot.");
}

DeleteDC(screen_dc);
DeleteDC(mem_dc);
*/

#elif defined(__APPLE__) && defined(__MACH__)
call_status = system("screencapture -x ~/screenfetch_screenshot.png 2> /dev/null");
#else
call_status = system("scrot ~/screenfetch_screenshot.png 2> /dev/null");
#endif

#if !defined(__CYGWIN__)
#if !defined(__CYGWIN__) && !defined(__MSYS__)
safe_strncpy(file_loc, getenv("HOME"), MAX_STRLEN);
strncat(file_loc, "/screenfetch_screenshot.png", MAX_STRLEN);

Expand Down

0 comments on commit f0a37e7

Please sign in to comment.