Would like some assistance.
I'm writing an app that takes a screenshot of a users screen and outputs a jpg.
I've written two seperate programs that I will share with you below.
First application works, but when I save it as a jpg, it distorts the quality. It makes the text "blurry" even though I set the highest quality.
The second application allows me to save it as an uncompressed image, and this image is a lot cleaner looking. However, the size is 7.91mb (which is BIG for a image). Then when I try converting it to jpg, I'm back with where I started and the newly created image is once again distorted\blurry.
I will include screenshot to show you what I mean.
App1:
Code:
// screenshot.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <GdiPlus.h>
#include <stdio.h>
#pragma comment( lib, "gdiplus" )
using namespace Gdiplus;
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
void gdiscreen()
{
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
EncoderParameters encoderParameters;
ULONG quality;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
{
HDC scrdc, memdc;
HBITMAP membit;
scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap =(HBITMAP) SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
//Let's optimize the picture quality
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 5;
quality = 100;
encoderParameters.Parameter[0].Value = &quality;
bitmap.Save(L"ScreenShot.jpg", &clsid, &encoderParameters);
SelectObject(memdc, hOldBitmap);
DeleteObject(memdc);
DeleteObject(membit);
ReleaseDC(0,scrdc);
}
GdiplusShutdown(gdiplusToken);
}
bool isRunning()
{
//This checks if the process is already running so you don't have multiple instances running.
HANDLE handle = CreateMutex(NULL, true, "screenshot");
if(GetLastError() != ERROR_SUCCESS)
{
MessageBox(0, "Process is already running", "Warning", MB_ICONWARNING);
return false;
}
else
return true;
}
int main()
{
//Don't show the console window
FreeConsole();
//Check if this process is running
if(isRunning() == false)
return 0;
//Run this loop until we explicitly close the process
while(1)
{
Sleep(5000);
gdiscreen();
}
return 0;
}
App2:
Code:
// screenshot.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <atlimage.h>
ATL::CImage img;
void ScreenShot(char*BmpName)
{
HWND DesktopHwnd = GetDesktopWindow();
RECT DesktopParams;
HDC DevC = GetDC(DesktopHwnd);
GetWindowRect(DesktopHwnd,&DesktopParams);
DWORD Width = GetSystemMetrics(SM_CXSCREEN);
DWORD Height = GetSystemMetrics(SM_CYSCREEN);
DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1*(Width*Height*4));
char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);
PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
PBITMAPINFOHEADER BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
BFileHeader->bfType = 0x4D42; // BM
BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
BInfoHeader->biPlanes = 1;
BInfoHeader->biBitCount = 32;
BInfoHeader->biCompression = BI_RGB;//BI_JPEG BI_RGB;
BInfoHeader->biHeight = Height;
BInfoHeader->biWidth = Width;
BInfoHeader->biSizeImage = Width * Height+1;
RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
SelectObject(CaptureDC,CaptureBitmap);
BitBlt(CaptureDC,0,0,Width,Height,DevC,0,0,SRCCOPY|CAPTUREBLT);
GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
DWORD Junk;
HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
WriteFile(FH,BmpFileData,FileSize,&Junk,0);
CloseHandle(FH);
GlobalFree(BmpFileData);
}
bool isRunning()
{
//This checks if the process is already running so you don't have multiple instances running.
HANDLE handle = CreateMutex(NULL, true, "screenshot");
if(GetLastError() != ERROR_SUCCESS)
{
MessageBox(0, "Process is already running", "Warning", MB_ICONWARNING);
return false;
}
else
return true;
}
int main()
{
//Don't show the console window
FreeConsole();
//Check if this process is running
if(isRunning() == false)
return 0;
//Run this loop until we explicitly close the process
while(1)
{
Sleep(5000);
ScreenShot("Screenshot.bmp");
img.Load(_T("Screenshot.bmp"));
img.Save(_T("Screenshot.jpg"), Gdiplus::ImageFormatJPEG );
img.Destroy();
img.ReleaseGDIPlus();
}
return 0;
}
Any suggestions?
EDIT:
I attached the compressed jpg file, but the bmp was giving me problems, so the file is here: http://www.x-null.net/Screenshot.bmp
You can tell the quality difference by looking at the red block with the black text. That's what I'm referring to.