Screenshot unter 500KB



  • Hey Liebe Leute,
    Ich habe ein Programm geschrieben mit dem ich nen Screenshot machen will welcher eine Größe von unter 500KB haben sollte.
    Da ich leider überhaupt keine Ahnung habe/hatte wie ich das realisieren soll habe ich gegoogelt, geoogelt und nochmal geoogelt.
    Ich habe zwar Zahlreiche Beispiele gefunden, welche auch funktionieren aber sie machen alle einen Screenshot mit über 4MB.
    In meiner Verzweiflung habe ich dann versucht es über PAINT zu machen aber diese Methode gefällt mir nicht,
    nicht weils nicht funktioniert sondern weil ich es richtig machen will.

    Hier nochmal der Paint - C++ Code :

    #define _WIN32_WINNT    0x0501        //xp
    #include <iostream>
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <fstream>
    
    wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
    {
        wchar_t* wString=new wchar_t[4096];
        MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
        return wString;
    }
    
    void TakeScreenShot(char* filename)
    {
    	//Make Screenshot
    	keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Creates the Image
    	std::ofstream a_file(filename);
    	a_file.close();
    
    	//Sleep for a short while
    	Sleep(10);
    
    	//Opens the Image secretly
    	ShellExecute(NULL, NULL, convertCharArrayToLPCWSTR("C:\\WINDOWS\\system32\\mspaint.exe"), convertCharArrayToLPCWSTR(filename), NULL, SW_HIDE );
    
    	//Sleep for a short while
    	Sleep(30);
    
    	//Sets paint to ForeGround
    	HWND windowHandel = FindWindow(0, convertCharArrayToLPCWSTR("Paint"));
    	SetForegroundWindow(windowHandel);  
    
    	//Paste Screenshot
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(86, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(86, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Paste Screenshot
    	keybd_event(VK_F12, 0x45, KEYEVENTF_EXTENDEDKEY, 0); Sleep(300);
    	keybd_event(VK_TAB, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_TAB, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_DOWN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_DOWN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);  
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_F12, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Save Screenshot
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(83, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(83, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    }
    
    int main()
    {
    
    	while(true){
    		if(GetAsyncKeyState(VkKeyScan('1'))){
    				TakeScreenShot("C:\\Users\\Tim\\Desktop\\Screenshot.bmp");
    		}
    	}
    
    }
    

    Und hier noch der Code aus Google *Nicht mein eigener* :

    #define _WIN32_WINNT    0x0501        //xp
    #include <iostream>
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <fstream>
    
    wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
    {
        wchar_t* wString=new wchar_t[4096];
        MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
        return wString;
    }
    
    void ScreenShot(char* BmpName)
    {
    	HWND DesktopHwnd = GetDesktopWindow();
    	RECT DesktopParams;
    	HDC DevC = GetDC(DesktopHwnd);
    	GetWindowRect(DesktopHwnd,&DesktopParams);
    	DWORD Width = DesktopParams.right - DesktopParams.left;
    	DWORD Height = DesktopParams.bottom - DesktopParams.top;
    
    	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 = 16	;
    	BInfoHeader->biCompression = BI_RGB;
    	BInfoHeader->biHeight = Height;
    	BInfoHeader->biWidth = Width;
    
    	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); 
    }
    
    int main()
    {
    
    	while(true){
    		if(GetAsyncKeyState(VkKeyScan('2'))){			
    			ScreenShot("C:\\Users\\Tim\\Desktop\\Screenshot.png");
    		}
    	}
    
    }
    

    Danke für jede Bemühung mir zu Helfen 🙂



  • TimDerVerzweifelte schrieb:

    Ich habe zwar Zahlreiche Beispiele gefunden, welche auch funktionieren aber sie machen alle einen Screenshot mit über 4MB.

    Besteht die Möglichkeit, sie nicht als BMP, sondern als PNG abzuspeichern?



  • volkard schrieb:

    Besteht die Möglichkeit, sie nicht als BMP, sondern als PNG abzuspeichern?

    Ja das Funktioniert aber das PNG hat dann trotzdem eine Größe von 7.91MB 😕
    Danke für den Versuch 🙂



  • Also wenn du den Screenshot als PNG 8Bit abspeicherst, dazu noch Dithering-Level ein wenig herunterschraubst, bekommst du locker ein Bild unter 500kb.
    Erwarte aber nicht zu hohe Qualität.



  • Hi schrieb:

    dazu noch Dithering-Level ein wenig herunterschraubst

    Hey, danke für deine Antwort 🙂

    Habe jetzt den

    BInfoHeader->biBitCount = 16;
    

    zu

    BInfoHeader->biBitCount = 8;
    

    umgetauscht, aber ich verstehe nicht ganz was du mit Dithering-Level meinst.

    EDIT :
    Ich glaube das so umzutauschen war nicht was du meinst, jetzt ist das Bild komplett grau O.o



  • Hier ein Artikel dazu: http://de.wikipedia.org/wiki/Dithering_(Bildbearbeitung)

    Ich habe durch das Senken des Dithering-Levels jedoch nur bei der PNG-Datei eine kleinere Größe bekommen. Beim Bitmap machte das keinen Unterschied.
    Ob du das hinbekommst kann ich dir nicht sagen, musst Du selbst Googeln.

    Du könntest auch JPEG verwenden. Ist ein sehr sparsames Format und hat trotzdem eine super Qualität.



  • Danke für den Wikipedia Link, aber gibt es da nicht eine einfachere Möglichkeit ?
    Ich glaube meinem Programm ist es völlig egal obs PNG, JPG, JPEG oder sonst was ist O.o



  • Schau mal hier: http://stackoverflow.com/a/1034609

    Dort wird deine Frage beantwortet. Dort wird das Bild als .jpeg abgespeichert.



  • Danke für den Link,
    Leider funktionieren die Beispiele nur mit GDIplus 😞
    Trotzdem danke 🙂



  • Und warum willst Du Gdiplus nicht verwenden?



  • TimDerVerzweifelte schrieb:

    volkard schrieb:

    Besteht die Möglichkeit, sie nicht als BMP, sondern als PNG abzuspeichern?

    Ja das Funktioniert aber das PNG hat dann trotzdem eine Größe von 7.91MB 😕
    Danke für den Versuch 🙂

    Screenshots von einer Anwendungen (ohne Hintergrundbild) werden als PNG total winzig.
    Außerdem packt es verlustfrei.
    JPG kommt da nicht mit, es wird größer und hat Farbabweichungen um die Buchstaben.

    Wenn im Bild Farbverläufe und sowas drin sind, dann halt JPG. Vor allem bei Fotos.

    BMP ist einfach groß.



  • @Unregistriert :
    Ich werde mich heute Abend mal an GDIplus dran setzen. Danke für die Hilfe 🙂

    @Volkard :
    Ne bei mir leider nicht, egal welches Format es bleibt bei der Größe..



  • TimDerVerzweifelte schrieb:

    @Volkard :
    Ne bei mir leider nicht, egal welches Format es bleibt bei der Größe..

    Bei genau der Größe?



  • Es reicht nicht, einfach nur die Dateinamenerweiterung auf ".png" zu ändern - du mußt schon eine entsprechende PNG-Library verwenden (bezogen auf deinen 2. Code)!



  • TimDerVerzweifelte schrieb:

    //Make Screenshot
    	keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Creates the Image
    	std::ofstream a_file(filename);
    	a_file.close();
    
    	//Sleep for a short while
    	Sleep(10);
    
    	//Opens the Image secretly
    	ShellExecute(NULL, NULL, convertCharArrayToLPCWSTR("C:\\WINDOWS\\system32\\mspaint.exe"), convertCharArrayToLPCWSTR(filename), NULL, SW_HIDE );
    
    	//Sleep for a short while
    	Sleep(30);
    
    	//Sets paint to ForeGround
    	HWND windowHandel = FindWindow(0, convertCharArrayToLPCWSTR("Paint"));
    	SetForegroundWindow(windowHandel);  
    
    	//Paste Screenshot
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(86, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(86, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Paste Screenshot
    	keybd_event(VK_F12, 0x45, KEYEVENTF_EXTENDEDKEY, 0); Sleep(300);
    	keybd_event(VK_TAB, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_TAB, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_DOWN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_DOWN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_UP, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_LEFT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);  
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(VK_RETURN, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_F12, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    
    	//Save Screenshot
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(83, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    	keybd_event(83, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    	keybd_event(VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
    

    😮
    Ich habe Angst vor dir...



  • volkard schrieb:

    TimDerVerzweifelte schrieb:

    @Volkard :
    Ne bei mir leider nicht, egal welches Format es bleibt bei der Größe..

    Bei genau der Größe?

    Jap 😕

    Th69 schrieb:

    Es reicht nicht, einfach nur die Dateinamenerweiterung auf ".png" zu ändern - du mußt schon eine entsprechende PNG-Library verwenden (bezogen auf deinen 2. Code)!

    Okay wollte aber eigentlich es mit der WinApi schaffen, bzw. ohne Library.



  • hustbaer schrieb:

    Ich habe Angst vor dir...

    😃 Warum ?



  • TimDerVerzweifelte schrieb:

    Okay wollte aber eigentlich es mit der WinApi schaffen, bzw. ohne Library.

    https://www.google.de/#q=save+png+msdn



  • volkard schrieb:

    TimDerVerzweifelte schrieb:

    Okay wollte aber eigentlich es mit der WinApi schaffen, bzw. ohne Library.

    https://www.google.de/#q=save+png+msdn

    Vielen Dank für den Google-Link.
    Aber wie gesagt ich habe schon gegoogelt und bin es langsam Leid.
    Der Link führt nur auf eine CLI seite bzw. wieder auf GDI+.
    Könnte mir nicht irgendwer einen Denkanstoß geben, veröffentliche dann auch meinen Code.



  • Was ist denn nun dein Problem mit GDI+? Alternativ kannst du WIC verwenden. Oder einen eigenen PNG-Encoder schreiben.


Anmelden zum Antworten