[C++] Read .gif from source

  • Autor subiect #TrC
  • Dată creare
  • Răspunsuri: Răspunsuri 0
  • Vizualizări: Vizualizări 47

#TrC

Fondator
Membru personal
11 Oct 2017
7.557
6.755
113
Monede Dragon
94
Se poate folosi pentru imagini de breasla, sisteme ce pot inlocui aniimage, interfete.. etc.
Cod:
* EterLib/GrpImage.cpp

Arat:
Code:

CGraphicImage::~CGraphicImage()
{
}


Üstüne ekle:
Code:

CGraphicImage::CGraphicImage(const char* c_szFileName, const void* c_pvBuf, int32_t iSize, uint32_t dwFilter) :
    CResource(c_szFileName),
    m_dwFilter(dwFilter)
{
    m_rect.bottom = m_rect.right = m_rect.top = m_rect.left = 0;
    Load(iSize, c_pvBuf);
}


* EterLib/GrpImage.h

Arat:
Code:

CGraphicImage(const char* c_szFileName, uint32_t dwFilter = D3DX_FILTER_LINEAR);


Altına ekle:
Code:

    CGraphicImage(const char* c_szFileName, const void* c_pvBuf, int32_t iSize, uint32_t dwFilter = D3DX_FILTER_LINEAR);


* EterLib/Resource.cpp

Arat:
Code:

void CResource::Reload()


Üstüne ekle:
Code:

void CResource::Load(int32_t iSize, const void* c_pvBuf)
{
    if (me_state != STATE_EMPTY)
        return;

    if (OnLoad(iSize, c_pvBuf))
        me_state = STATE_EXIST;
    else
        me_state = STATE_ERROR;

    //Tracef("CResource::Load %s\n", GetFileName());
}


* EterLib/Resource.h
Arat:
Code:

    void            Load();


Altına ekle:
Code:

    void            Load(int32_t iSize, const void* c_pvBuf);


* EterPythonLib/PythonWindow.cpp

Ekle:
Code:

#include <gif_lib.h>
#include <wingdi.h>


--

Arat:
Code:

    void CAniImageBox::OnEndFrame()
    {
        PyCallClassMemberFunc(m_poHandler, "OnEndFrame", BuildEmptyTuple());
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////


Altına ekle:
Code:

    uint32_t CGifImageBox::Type()
    {
        static uint32_t s_dwType = GetCRC32("CGifImageBox", strlen("CGifImageBox"));
        return (s_dwType);
    }

    BOOL CGifImageBox::OnIsType(uint32_t dwType)
    {
        if (CGifImageBox::Type() == dwType)
            return TRUE;

        return FALSE;
    }

    CGifImageBox::CGifImageBox(PyObject* ppyObject)
        : CAniImageBox(ppyObject)
    {
    }
    CGifImageBox::~CGifImageBox()
    {
    }

    bool RawFrameToBmpImage(SavedImage* currentFrame, GifFileType* gifFile, std::vector <uint8_t>& outData)
    {
        if (!currentFrame || !gifFile)
        {
            TraceError("RawFrameToBmpImage: Invalid parameters.");
            return false;
        }

        auto& imageDesc = currentFrame->ImageDesc;
        auto* colorMap = (imageDesc.ColorMap) ? imageDesc.ColorMap : gifFile->SColorMap;
        if (!colorMap)
        {
            TraceError("RawFrameToBmpImage: ColorMap is null.");
            return false;
        }

        const int width = imageDesc.Width;
        const int height = imageDesc.Height;
        const int rowPadding = (4 - (width * 3 % 4)) % 4;
        const std::size_t rowDataSize = static_cast<std::size_t>(width * 3 + rowPadding) * height;

        BITMAPFILEHEADER fileHeader = {
            0x4D42, // "BM"
            static_cast<uint32_t>(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + rowDataSize),
            0, // Reserved1
            0, // Reserved2
            sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
        };

        BITMAPINFOHEADER infoHeader = {
            sizeof(BITMAPINFOHEADER),
            width,
            height,
            1, // Planes
            24, // BitCount
            0, // Compression
            static_cast<uint32_t>(rowDataSize),
            0, // XPelsPerMeter
            0, // YPelsPerMeter
            0, // ClrUsed
            0  // ClrImportant
        };

        outData.resize(fileHeader.bfSize);
        std::memcpy(outData.data(), &fileHeader, sizeof(fileHeader));
        std::memcpy(outData.data() + sizeof(fileHeader), &infoHeader, sizeof(infoHeader));

        auto pixelData = outData.begin() + fileHeader.bfOffBits;
        for (int y = height - 1; y >= 0; --y)
        {
            for (int x = 0; x < width; ++x)
            {
                const int index = y * width + x;
                const GifByteType colorIndex = currentFrame->RasterBits[index];
                const GifColorType& gifColor = colorMap->Colors[colorIndex];

                *pixelData++ = gifColor.Blue;
                *pixelData++ = gifColor.Green;
                *pixelData++ = gifColor.Red;
            }
            pixelData = std::fill_n(pixelData, rowPadding, 0x00);
        }
    }

    bool CGifImageBox::LoadGif(const char* c_szFileName)
    {
        if (!c_szFileName || !*c_szFileName)
            return false;

        // Open GIF file
        int error;
        GifFileType* gif = DGifOpenFileName(c_szFileName, &error);
        if (!gif)
        {
            const char* c_szError = GifErrorString(error);
            TraceError("Failed to open GIF file: %s with error: %s", c_szFileName, c_szError);
            return false;
        }

        // Read the GIF into memory
        if (DGifSlurp(gif) == GIF_ERROR)
        {
            TraceError("Failed to read GIF file: %s", c_szFileName);
            DGifCloseFile(gif, &error);
            return false;
        }

        // Iterate through the frames
        for (int i = 0; i < gif->ImageCount; ++i)
        {
            // Get the current frame
            SavedImage* currentImage = &gif->SavedImages[i];

            // Convert the frame to BMP image
            std::vector <uint8_t> bmpBuffer;
            if (!RawFrameToBmpImage(currentImage, gif, bmpBuffer))
            {
                TraceError("Failed to convert GIF(%s) frame #%d to BMP image.", c_szFileName, i);
                continue;
            }

            // Create name for the frame
            char frameFileName[256]{ '\0' };
            snprintf(frameFileName, sizeof(frameFileName), "gif_frame%d_%s", i, c_szFileName);

            // Create the image instance
            CGraphicImage* pImage = new CGraphicImage(frameFileName, bmpBuffer.data(), bmpBuffer.size(), D3DX_FILTER_LINEAR);
            if (!pImage)
            {
                TraceError("Failed to create image instance for GIF(%s) frame #%d.", c_szFileName, i);
                continue;
            }

            // Create the expanded image instance
            CGraphicExpandedImageInstance* pImageInstance = CGraphicExpandedImageInstance::New();
            pImageInstance->SetImagePointer(pImage);

            // Add the image instance to the vector if it's not empty
            if (pImageInstance->IsEmpty())
            {
                CGraphicExpandedImageInstance::Delete(pImageInstance);
            }
            else
            {
                pImageInstance->SetPosition(m_rect.left, m_rect.top);
                m_ImageVector.push_back(pImageInstance);
            }
        }

        // Clean up
        DGifCloseFile(gif, &error);

        return true;
    }

    bool CGifImageBox::UnloadGif()
    {
        for (auto pImage : m_ImageVector)
            CGraphicExpandedImageInstance::Delete(pImage);

        m_ImageVector.clear();
        return true;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////


* EterPythonLib/PythonWindow.h

Arat:
Code:

    // Button
    class CButton : public CWindow


Üstüne ekle:
Code:

    class CGifImageBox : public CAniImageBox
    {
    public:
        static uint32_t Type();

        public:
            CGifImageBox(PyObject* ppyObject);
            virtual ~CGifImageBox();

            bool LoadGif(const char* c_szFileName);
            bool UnloadGif();

        protected:
            BOOL OnIsType(uint32_t dwType);
    };


* EterPythonLib\PythonWindowManager.cpp

Arat:
Code:

        case WT_ANI_IMAGEBOX:
            return new CAniImageBox(po);
            break;


Altına ekle:
Code:

        case WT_GIF_IMAGEBOX:
            return new CGifImageBox(po);
            break;


---

Arat:
Code:

    CWindow* CWindowManager::RegisterAniImageBox(PyObject* po, const char* c_szLayer)
    {
        assert(m_LayerWindowMap.end() != m_LayerWindowMap.find(c_szLayer));

        CWindow* pWin = new CAniImageBox(po);
        m_LayerWindowMap[c_szLayer]->AddChild(pWin);

#ifdef __WINDOW_LEAK_CHECK__
        gs_kSet_pkWnd.insert(pWin);
#endif
        return pWin;
    }


Altına ekle:
Code:

    CWindow* CWindowManager::RegisterGifImageBox(PyObject* po, const char* c_szLayer)
    {
        assert(m_LayerWindowMap.end() != m_LayerWindowMap.find(c_szLayer));

        CWindow* pWin = new CGifImageBox(po);
        m_LayerWindowMap[c_szLayer]->AddChild(pWin);

#ifdef __WINDOW_LEAK_CHECK__
        gs_kSet_pkWnd.insert(pWin);
#endif
        return pWin;
    }


* EterPythonLib\PythonWindowManager.h

Arat:
Code:

            WT_ANI_IMAGEBOX,


Altına ekle:
Code:

            WT_GIF_IMAGEBOX,


--

Arat:
Code:

        CWindow* RegisterImageBox(PyObject* po, const char* c_szLayer);


Altına ekle:
Code:

        CWindow* RegisterGifImageBox(PyObject* po, const char* c_szLayer);


* EterPythonLib\PythonWindowManagerModule.cpp

Ekle:
Code:

PyObject* wndMgrRegisterGifImageBox(PyObject* poSelf, PyObject* poArgs)
{
    PyObject* po;
    if (!PyTuple_GetObject(poArgs, 0, &po))
        return Py_BuildException();
    char* szLayer;
    if (!PyTuple_GetString(poArgs, 1, &szLayer))
        return Py_BuildException();

    UI::CWindow* pWindow = UI::CWindowManager::Instance().RegisterGifImageBox(po, szLayer);
    return Py_BuildValue("i", pWindow);
}

PyObject* wndGifImageLoadGif(PyObject* poSelf, PyObject* poArgs)
{
    UI::CWindow* pWindow;
    if (!PyTuple_GetWindow(poArgs, 0, &pWindow))
        return Py_BuildException();
    char* szFileName;
    if (!PyTuple_GetString(poArgs, 1, &szFileName))
        return Py_BuildException();

    ((UI::CGifImageBox*)pWindow)->LoadGif(szFileName);

    return Py_BuildNone();
}
PyObject* wndGifImageUnloadGif(PyObject* poSelf, PyObject* poArgs)
{
    UI::CWindow* pWindow;
    if (!PyTuple_GetWindow(poArgs, 0, &pWindow))
        return Py_BuildException();

    ((UI::CGifImageBox*)pWindow)->UnloadGif();

    return Py_BuildNone();
}


:
Code:

        { "RegisterAniImageBox",        wndMgrRegisterAniImageBox,            METH_VARARGS },


:
Code:

        { "RegisterGifImageBox",        wndMgrRegisterGifImageBox,            METH_VARARGS },
        { "LoadGif",                    wndGifImageLoadGif,                    METH_VARARGS },
        { "UnloadGif",                    wndGifImageUnloadGif,                METH_VARARGS },


*ScriptLib\Resource.cpp

Arat:
Code:

    m_resManager.RegisterResourceNewFunctionPointer("bmp", NewImage);


Altına ekle:
Code:

    m_resManager.RegisterResourceNewFunctionPointer("gif", NewImage);


* UserInterface\UserInterface.cpp
Code:

#pragma comment( lib, "gif.lib" )


---

* root/ui.py


Code:

class GifBox(Window):
    def __init__(self, layer = "UI"):
        Window.__init__(self, layer)

        self.eventDict={}
        self.arg = -1
        self.argOut = -1
        self.imageLoaded = False

    def __del__(self):
        Window.__del__(self)

    def RegisterWindow(self, layer):
        self.hWnd = wndMgr.RegisterGifImageBox(self, layer)

    def LoadImage(self, imageName):
        self.name=imageName
        wndMgr.LoadGif(self.hWnd, imageName)
        self.imageLoaded = True

        if len(self.eventDict)!=0:
            print "LOAD IMAGE", self, self.eventDict

    def UnloadImage(self):
        if self.imageLoaded:
            wndMgr.UnloadGif(self.hWnd)
            self.imageLoaded = False

    def SetAlpha(self, alpha):
        wndMgr.SetDiffuseColor(self.hWnd, 1.0, 1.0, 1.0, alpha)

    def SetDiffuseColor(self, r,g,b,a=1.0):
        wndMgr.SetDiffuseColor(self.hWnd, r,g,b,a)

    def SetAlphaColor(self, r,g,b,alpha=1.0):
        wndMgr.SetDiffuseColor(self.hWnd, r,g,b, alpha)

    def GetWidth(self):
        return wndMgr.GetWidth(self.hWnd)

    def GetHeight(self):
        return wndMgr.GetHeight(self.hWnd)

  
    def SetRenderingRect(self, left, top, right, bottom):
        wndMgr.SetRenderingRect(self.hWnd, left, top, right, bottom)

    def SetPercentage(self, curValue, maxValue):
        if maxValue:
            self.SetRenderingRect(0.0, 0.0, -1.0 + float(curValue) / float(maxValue), 0.0)
        else:
            self.SetRenderingRect(0.0, 0.0, 0.0, 0.0)

  
    def SetScale(self, xScale, yScale):
        wndMgr.SetScale(self.hWnd, xScale, yScale)


---

Download extern: https://www.dosyaupload.com/1rzkp/giflib.zip