# [C/C++] Screenshot als JPEG/TIFF speichern



## elbdom (18. April 2011)

Hallo Leute,

Habe folgendes Problem ich schaffe es mit meinen C/C++ Code einen Screenshot zu erzeugen und ihn als BMP ab zu speichern aber nicht ihn als JPEG oder TIFF ab zu speichern.
ich habe nach gegoogelt aber nicht gefunden wie ich ohne standert Libs in C/C++ das bild so abspeichern kann oder zu mindestens convatieren kann.
hier mal mein code:

```
#include <windows.h>

/* <Function> */
void SaveScreen(HWND pScreen, char Path[])
{
	int     Width  = GetSystemMetrics(SM_CXSCREEN);//1280;
	int     Height = GetSystemMetrics(SM_CYSCREEN);//1024;

    HDC hdcScreen;
    HBITMAP hbmScreen;


    //---------------Bitmap Informationen
    BITMAPINFO infobmp;
    infobmp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    infobmp.bmiHeader.biWidth = Width;
    infobmp.bmiHeader.biHeight = Height;
    infobmp.bmiHeader.biPlanes = 1;
    infobmp.bmiHeader.biBitCount = 24;
    infobmp.bmiHeader.biCompression = 16;
    infobmp.bmiHeader.biSizeImage = 0;
    infobmp.bmiHeader.biXPelsPerMeter = 0;
    infobmp.bmiHeader.biYPelsPerMeter = 0;
    infobmp.bmiHeader.biClrUsed = 0;
    infobmp.bmiHeader.biClrImportant = 0;

    int* bitmap = new int[Width*Height*3];

    BITMAPFILEHEADER bfheader;

    bfheader.bfType = 19778;
    bfheader.bfSize = sizeof(BITMAPFILEHEADER) + Width*Height*3 + sizeof(BITMAPINFOHEADER);
    bfheader.bfReserved1 = 0;
    bfheader.bfReserved2 = 0;
    bfheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    //Bitmap -----------------------      Informationen


    hdcScreen = GetWindowDC(pScreen);
    hbmScreen = CreateCompatibleBitmap(hdcScreen, Width, Height);

    // temporärer DC
    HDC hdcTemp = CreateCompatibleDC(hdcScreen);

    // Bitmap reinselektieren
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcTemp, hbmScreen);

    // Inhalt von Desktop übertragen
    BitBlt(hdcTemp, 0, 0, Width, Height, hdcScreen, 0, 0, SRCCOPY);

    int iResult = GetDIBits(hdcTemp, hbmScreen, 0, Height, bitmap, &infobmp, DIB_RGB_COLORS);

    // aufräumen
    SelectObject(hdcTemp, hbmOld);
    DeleteObject(hbmScreen);
    DeleteDC(hdcTemp);

    HANDLE hfile = CreateFile(Path, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);

    //Datei Schreiben
    DWORD word;
    WriteFile(hfile, &bfheader, 14, &word, NULL);
    WriteFile(hfile, &infobmp, 40,& word, NULL);
    WriteFile(hfile, bitmap, Width*Height*3, &word,NULL);

    ReleaseDC(pScreen, hdcScreen);
    CloseHandle(hfile);
    delete[] bitmap;
}
/* </Function> */

int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
	HWND hWnd = FindWindow(NULL, AppName);


	char *path="C:/neu.bmp";
	Sleep(1000);
	SaveScreen(hWnd, path);

	return 0;
}
```


----------



## Bratkartoffel (18. April 2011)

Hi,

wie meinst du das "ohne Standard-Libs"? Meinst du ohne externe Bibliotheken?

Gruß
BK


----------



## sheel (18. April 2011)

Hi

warum willst du keine Libs verwenden?
Dazu gibts sie ja, um das Ganze einfacher zu machen.

Die engl. Wikipedia gibt jedenfalls einen Einblick in den Aufbau von JPEG und weiterführende Links, sicher auch für TIFF.

Gruß


----------



## MCoder (18. April 2011)

Hallo,

da es sich ja wohl um Windows handelt: Mit GDI+ lassen sich auch TIFF, JPG, PNG und GIF schreiben. 

Gruß
MCoder


----------



## elbdom (18. April 2011)

Ups vergessen ja erstmal es Handelt sich um Windows und ich meine mit standert Libs die bei Windows beiliegen will das es nur eine exe ist ohne zusätzliche Libs die ich beiliegen muss.


----------



## Bratkartoffel (18. April 2011)

Hi,

du könntest die Libs auch statisch dazu linken, dann hast auch nur eine exe 

Gruß
BK


----------



## elbdom (18. April 2011)

ich habe mich falsch ausgedrückt ich möchte halt eins was Platform unabhängig ist und beim statischen linken wird die exe ziemlich groß

ambesten wäre es mit der Winapi


----------



## Bratkartoffel (18. April 2011)

Hi,

sobald du die Win-Api verwendest, bist nicht mehr plattform-unabhängig.
Wenn du jetzt allerdings eine Bibliothek nimmst und diese als Quelltext vorliegt, dann kann es unter Umständen auf mehreren System-Typen laufen.

Gruß
BK


----------



## elbdom (18. April 2011)

Windows platform unabhängig also das ich sagen kann ich nehme das tool und gebe es jemand anders der nur windows(XP/Vista/7) ohne GDI oder .net drauf hat und es läuft sofort ohne erst was nach zu installieren


----------



## MCoder (18. April 2011)

GDI+ ist ab Windows XP Bestandteil des Betriebssystems.

Gruß
MCoder


----------



## elbdom (18. April 2011)

ok und wie stelle ich es nun abesten an wenn ich es jetzt als jpeg speichern möchte?


----------



## MCoder (18. April 2011)

Wenn ein halbwegs aktuelles Windows SDK installiert ist, sollte das kleine Beispiel ohne Probleme laufen.

```
#ifdef _WIN64
typedef unsigned __int64 ULONG_PTR;
#else
typedef unsigned long ULONG_PTR;
#endif

#include <windows.h>
#include <gdiplus.h>
#include <string>
#pragma comment (lib, "gdiplus.lib")
 
int main()
{
    // Initialisierung (nur einmal im Programm)
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    // Irgendein Bmp zum Testen
    
    HBITMAP hbm = (HBITMAP)LoadImage( NULL,
                                      "C:\\test.bmp",
                                      IMAGE_BITMAP,
                                      0,
                                      0,
                                      LR_LOADFROMFILE );
                             
    Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromHBITMAP(hbm, (HPALETTE)GetStockObject(DEFAULT_PALETTE));                             

    // Encoder ermitteln und speichern

    UINT nNum, nSize;
    Gdiplus::GetImageEncodersSize(&nNum, &nSize);

    Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo *)new char[nSize];
    Gdiplus::GetImageEncoders(nNum, nSize, pImageCodecInfo);

    for( UINT i = 0; i < nNum; i++ )
    {
        std::wstring wstrMime = pImageCodecInfo[i].MimeType;

        if( wstrMime == L"image/jpeg" ) // oder image/gif, image/tiff, image/png, image/bmp
        {
            pBitmap->Save( L"C:\\test.jpg", &pImageCodecInfo[i].Clsid);
            break;
        }
    }

    delete pImageCodecInfo;
    delete pBitmap;
    DeleteObject(hbm);

    // Deinitialisierung
    Gdiplus::GdiplusShutdown(gdiplusToken);
    return 0;
}
```
Gruß
MCoder


----------

