[C++ / Py] DirectX9 ile Daha Kaliteli Ekran Görüntüsü Alma

Kaiser

⋞ 〈 ☪ 〉 ⋟
Site yetkilisi
Admin
Premium Üye
Geliştirici
Yardımsever Üye
Mesaj
3.695
Çözümler
345
Beğeni
3.585
Puan
1.849
Ticaret Puanı
0
Merhaba. Bildiğiniz gibi Metin2'de ki LibJPEG kütüphanesi sadece ekran görüntüsü almaya yarıyor. Bunun haricinde herhangi bir görevi yok.
Directx9'a sahip olanlar ve bu yöntem ile daha kaliteli ekran görüntüleri almak isteyenler bu rehberi dikkatlice uygulayabilirler.
Directx8 kullananlar ise vereceğim kodu Directx8'e göre güncelleyip deneyebilirler, benim deneme şansım olmadı.

Buradaki işlemleri uygulamadan önce kararlı olduğunuzdan emin olun. Çünkü bu işlemlerin sonucunda hem artık libjpeg kütüphanesine sahip olmayacaksınız, hem de ekran görüntüsü dosyaları kaliteye bağlı olarak jpg dosyasına göre daha büyük boyutlara ulaşacaktır. (3-8 MB arası)
Anlatım biraz karma olacaktır ancak her işlemi sırasıyla yaptığınızda herhangi bir sorun yaşamayacaksınız. Yine de bir sorun yaşarsanız konu altından belirtebilirsiniz.

Fark görseli en aşağıya eklenmiştir.


Öncelikle libjpeg'den kurtulalım:
  • Client src/extern/lib klasörüne girin ve dosya ismi libjpeg.. ile başlayan .lib dosyalarını silin.
  • Client src/EterLib klasörüne girin ve JpegFile.cpp & JpegFile.h dosyalarını silin. Visual Studio'da da aynı şekilde EterLib projesini açıp, bu iki dosyayı seçin ve kaldırın.
  • Client src/EterPythonLib/PythonGraphic.cpp dosyasını açın ve şu include satırını ve fonksiyonları kaldırın:
    C++:
    #include "../eterLib/JpegFile.h"
    
    
    void GenScreenShotTag(const char* src, DWORD crc32, char* leaf, size_t leafLen){
        const char* p = src;
        const char* n = p;
        while (n = strchr(p, '\\'))
            p = n + 1;
    
        _snprintf(leaf, leafLen, "YMIR_METIN2:%s:0x%.8x", p, crc32);
    }
    
    bool CPythonGraphic::SaveJPEG(const char* pszFileName, LPBYTE pbyBuffer, UINT uWidth, UINT uHeight)
    {
        return jpeg_save(pbyBuffer, uWidth, uHeight, 100, pszFileName) != 0;
    }
  • Bunları sildiğiniz yerde şu fonksiyonu göreceksiniz:
    C++:
    bool CPythonGraphic::SaveScreenShot(const char* c_pszFileName)
    {
  • Bu fonksiyonu tamamen şu şekilde değiştirin:
  • C++:
    bool CPythonGraphic::SaveScreenShot()
    {
        LPDIRECT3DSURFACE9 lpSurface = nullptr;
        D3DSURFACE_DESC stSurfaceDesc = {};
    
        uint32_t uWidth = stSurfaceDesc.Width;
        uint32_t uHeight = stSurfaceDesc.Height;
    
        ms_lpd3dDevice->CreateOffscreenPlainSurface(uWidth, uHeight, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &lpSurface, NULL);
    
        if (SUCCEEDED(ms_lpd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &lpSurface)))
        {
            if (!CreateDirectory("screenshot", NULL) && ERROR_ALREADY_EXISTS != GetLastError()) //yoksa oluştur
                return false;
    
    
            SYSTEMTIME st;
            GetSystemTime(&st);
            char szFileName[MAX_PATH];
            sprintf_s(szFileName, "screenshot/screenshot_%04d%02d%02d_%02d%02d%02d.bmp", // eşsiz
                st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    
            D3DXSaveSurfaceToFile(szFileName, D3DXIFF_BMP, lpSurface, NULL, NULL);
        }
        else
            TraceError("CPythonGraphic::SaveScreenShot() - ScreenShot Basarisiz!");
    
        // yok et
        if (lpSurface)
        {
            lpSurface->Release();
            lpSurface = nullptr;
        }
    
        return true;
    }


  • Ardından PythonGraphic.h dosyasından ise şunu kaldırın:
    C++:
    bool SaveJPEG(const char* pszFileName, LPBYTE pbyBuffer, UINT uWidth, UINT uHeight);
  • Aynı dosyada şu mevcut olacaktır;
    C++:
    bool SaveScreenShot(const char* szFileName);
    Bunu şu şekilde güncelleyin:
    C++:
    bool SaveScreenShot();
  • PythonGraphicModule.cpp dosyasını açın ve şunu silin:
    C++:
    PyObject* grpSaveScreenShot(PyObject* poSelf, PyObject* poArgs)
    {
        struct tm* tmNow;
        time_t ct;
    
        ct = time(0);
        tmNow = localtime(&ct);
    
        char szPath[MAX_PATH + 256];
        SHGetSpecialFolderPath(NULL, szPath, CSIDL_PERSONAL, TRUE);
        //GetTempPath();
        strcat(szPath, "\\METIN2\\");
    
        if (-1 == _access(szPath, 0))
            if (!CreateDirectory(szPath, NULL))
            {
                TraceError("Failed to create directory [%s]\n", szPath);
                return Py_BuildValue("(is)", FALSE, "");
            }
    
        sprintf(szPath + strlen(szPath), "%02d%02d_%02d%02d%02d.jpg",
            tmNow->tm_mon + 1,
            tmNow->tm_mday,
            tmNow->tm_hour,
            tmNow->tm_min,
            tmNow->tm_sec);
    
        BOOL bResult = CPythonGraphic::Instance().SaveScreenShot(szPath);
        return Py_BuildValue("(is)", bResult, szPath);
    }
  • Daha sonra ise şunu silin:
    C++:
    { "SaveScreenShot",                grpSaveScreenShot,                METH_VARARGS },
  • Aynı dosya içinde şu fonksiyonu bulun:

    C++:
    PyObject* grpSaveScreenShotToPath(PyObject* poSelf, PyObject* poArgs)
    {
  • Bu fonksiyonu aşağıda verdiğim kod ile tamamen değiştirin:
    C++:
    PyObject* grpSaveScreenShotToPath(PyObject* poSelf, PyObject* poArgs)
    {
        CPythonGraphic::Instance().SaveScreenShot();
        return Py_BuildNone();
    }
Client src ile işimiz bitti. Şimdi root/game.py açın ve şu fonksiyonu bulun:

C++:
    def SaveScreen(self):
        print "save screen"

        # SCREENSHOT_CWDSAVE
        if SCREENSHOT_CWDSAVE:
            if not os.path.exists(os.getcwd()+os.sep+"screenshot"):
                os.mkdir(os.getcwd()+os.sep+"screenshot")

            (succeeded, name) = grp.SaveScreenShotToPath(os.getcwd()+os.sep+"screenshot"+os.sep)
        elif SCREENSHOT_DIR:
            (succeeded, name) = grp.SaveScreenShot(SCREENSHOT_DIR)
        else:
            (succeeded, name) = grp.SaveScreenShot()
        # END_OF_SCREENSHOT_CWDSAVE

        if succeeded:
            pass
            """
            chat.AppendChat(chat.CHAT_TYPE_INFO, name + localeInfo.SCREENSHOT_SAVE1)
            chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.SCREENSHOT_SAVE2)
            """
        else:
            chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.SCREENSHOT_SAVE_FAILURE)

..ve şu şekilde güncelleyin:

C++:
    def SaveScreen(self):
        grp.SaveScreenShotToPath()

Sonuç olarak genel fark aşağıda göründüğü gibidir. Daha anlaşılır olması için zoom yaparak göstermek istedim. Görüntü dosyasının boyutu oyunu oynadığınız pencere boyutuna göre değişecektir. Sağ taraftaki görsel 1920x1080 olduğu için dosya boyutu 7.97 MB olarak kaydedildi.
Ekran görüntüsü 2023-12-21 170919.png
 
teşekkürler ama bu boyutta bir yere yüklerken sıkıntı çıkarabilir
 
teşekkürler ama bu boyutta bir yere yüklerken sıkıntı çıkarabilir
Evet, zaten bu ve benzeri faktörler için
Buradaki işlemleri uygulamadan önce kararlı olduğunuzdan emin olun. Çünkü bu işlemlerin sonucunda hem artık libjpeg kütüphanesine sahip olmayacaksınız, hem de ekran görüntüsü dosyaları kaliteye bağlı olarak jpg dosyasına göre daha büyük boyutlara ulaşacaktır. (3-8 MB arası)
şeklinde bir uyarı belirttim. Artık gerisi kullanıcıya kalmış.
 
Geri
Üst