void ModelOpened::ExportPNG(wxString val, wxString suffix)
{
	if (val == wxEmptyString)
		return;
	wxFileName fn = fixMPQPath(val);
	if (fn.GetExt().Lower() != wxT("blp"))
		return;
	TextureID temptex = texturemanager.add(val);
	Texture &tex = *((Texture*)texturemanager.items[temptex]);
	if (tex.w == 0 || tex.h == 0)
		return;

	wxString temp;

	unsigned char *tempbuf = (unsigned char*)malloc(tex.w*tex.h*4);
	tex.getPixels(tempbuf, GL_BGRA_EXT);

	CxImage *newImage = new CxImage(0);
	newImage->AlphaCreate();	// Create the alpha layer
	newImage->IncreaseBpp(32);	// set image to 32bit 
	newImage->CreateFromArray(tempbuf, tex.w, tex.h, 32, (tex.w*4), true);
	if (bPathPreserved) {
		wxFileName::Mkdir(wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetPath(), 0755, wxPATH_MKDIR_FULL);
		temp = wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetPath()+SLASH+fn.GetName()+wxT(".")+suffix;
	} else {
		temp = wxGetCwd()+SLASH+wxT("Export")+SLASH+fn.GetName()+wxT(".")+suffix;
	}
	//wxLogMessage(wxT("Info: Exporting texture to %s..."), temp.c_str());
	if (suffix == wxT("tga"))
#ifndef _MINGW
		newImage->Save(temp.mb_str(), CXIMAGE_FORMAT_TGA);
#else
		newImage->Save(temp.wc_str(), CXIMAGE_FORMAT_TGA);
#endif
	else
Exemple #2
0
// This must be called before any frame-saving is attempted.
void CAnimationExporter::CreateGif()
{
    if(!g_canvas || !g_canvas->model || !g_canvas->model->animManager)
    {
        wxMessageBox(_T("Unable to create animated GIF!"), _T("Error") );
        wxLogMessage(_T(
            "Error: Unable to created animated GIF.  A required objects pointer was null!") );
        Show(false);
        return ;
    }

    CxImage **gifImages = NULL; // Our pointer array of images

    // Reset the state of our GUI objects
    btnStart->Enable(false);
    btnCancel->Enable(false);
    cbGrey->Enable(false);
    cbTrans->Enable(false);
    cbDither->Enable(false);
    cbShrink->Enable(false);
    txtFrames->Enable(false);
    txtSizeX->Enable(false);
    txtSizeY->Enable(false);
    txtDelay->Enable(false);

    // Pause our rendering to screen so we can focus on making the animated image
    g_videoSetting.render = false;

    m_fAnimSpeed = g_canvas->model->animManager->GetSpeed(); 
        // Save the old animation speed
    g_canvas->model->animManager->SetSpeed(1.0f); // Set it to the normal speed.

    m_iTotalAnimFrames = g_canvas->model->animManager->GetFrameCount();
    wxString(txtFrames->GetValue() ).ToLong( (long*) &m_iTotalFrames);
    wxString(txtDelay->GetValue() ).ToLong( (long*) &m_iDelay);

    // will crash program - prevent this from happening
    if(m_iTotalFrames > m_iTotalAnimFrames)
    {
        wxMessageBox(_T(
            "Impossible to make a gif with more frames than the model animation.\nClosing gif exporter."), _T("Error") );
        wxLogMessage(_T(
            "Error: Unable to make a gif with more frames than the model animation.") );
        this->Show(false);
        return ;
    }

    if(m_iDelay < 1)
    {
        m_iDelay = 1;
    }
    if(m_iDelay > 100)
    {
        m_iDelay = 100;
    }

    m_iTimeStep = int(m_iTotalAnimFrames / m_iTotalFrames); 
        // Total number of frames in the animation / total frames going into our exported animation image

    if(m_bShrink)
    {
        wxString(txtSizeX->GetValue() ).ToLong( (long*) &m_iNewWidth);
        wxString(txtSizeY->GetValue() ).ToLong( (long*) &m_iNewHeight);

        // Just a minor check,  final image size can not be smaller than 32x32 pixels.
        if(m_iNewWidth < 32 || m_iNewHeight < 32)
        {
            m_iNewWidth = 32;
            m_iNewHeight = 32;
        }
    }

    // CREATE OUR RENDERTOTEXTURE OBJECT
    // -------------------------------------------
    // if either are supported use our 'RenderTexture' object.
    if(g_videoSetting.supportPBO || g_videoSetting.supportVBO)
    {
        g_canvas->rt = new RenderTexture();

        if(!g_canvas->rt)
        {
            wxLogMessage(_T("Error: RenderToTexture object is null!") );
            this->Show(false);
            return ;
        }

        g_canvas->rt->Init( (HWND)g_canvas->GetHandle(), 0, 0, g_videoSetting.supportFBO)
            ;

        m_iWidth = g_canvas->rt->nWidth;
        m_iHeight = g_canvas->rt->nHeight;
        g_canvas->rt->BeginRender();
    }
    else
    {
        glReadBuffer(GL_BACK);
        int screenSize[4];
        glGetIntegerv(GL_VIEWPORT, screenSize); 
            // get the width/height of the canvas
        m_iWidth = screenSize[2];
        m_iHeight = screenSize[3];
        return ;
    }

    // Stop our animation
    g_canvas->model->animManager->Pause(true);
    g_canvas->model->animManager->Stop();
    g_canvas->model->animManager->AnimateParticles();

    // Size of our buffer to hold the pixel data
    m_iSize = m_iWidth * m_iHeight * 4; // (width*height*bytesPerPixel)	

    // Create one frame to make our optimal colour palette from.
    unsigned char *buffer = new unsigned char[m_iSize];
    gifImages = new CxImage *[m_iTotalFrames];

    for(unsigned int i = 0; i < m_iTotalFrames; i++)
    {
        lblCurFrame->SetLabel(wxString::Format(_T("Current Frame: %i"), i) );

        this->Refresh();
        this->Update();

        CxImage *newImage = new CxImage(0);

        g_canvas->RenderToBuffer();

        glReadPixels(0, 0, m_iWidth, m_iHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
            buffer);
        newImage->CreateFromArray(buffer, m_iWidth, m_iHeight, 32, (m_iWidth *4)
            , false);

        // not needed due to the code just below, which fixes the issue with particles
        //g_canvas->model->animManager->SetTimeDiff(m_iTimeStep);
        //g_canvas->model->animManager->Tick(m_iTimeStep);

        if(g_canvas->root)
        {
            g_canvas->root->tick( (float)m_iTimeStep);
        }
        if(g_canvas->sky)
        {
            g_canvas->sky->tick( (float)m_iTimeStep);
        }


#ifdef _WIN32
        if(m_bGreyscale)
        {
            newImage->GrayScale();
        }
#endif //_WIN32

        if(m_bShrink && m_iNewWidth != m_iWidth && m_iNewHeight != m_iHeight)
        {
            newImage->Resample(m_iNewWidth, m_iNewHeight, 2);
        }

        // if (Optimise) {
        if(!m_pPal)
        {
            CQuantizer q(256, 8);
            q.ProcessImage( (HANDLE)newImage->GetDIB() );
            m_pPal = (RGBQUAD*)calloc(256 *sizeof(RGBQUAD), 1); 
                //This creates our gifs optimised global colour palette
            q.SetColorTable(m_pPal);
        }

        newImage->DecreaseBpp(8, m_bDiffuse, m_pPal, 256);
        newImage->SetCodecOption(2); // for LZW compression

        if(m_bTransparent)
        {
            newImage->SetTransIndex(newImage->GetPixelIndex(0, 0) );
        }

        newImage->SetFrameDelay(m_iDelay);

        gifImages[i] = newImage;

        // All the memory that we allocate for newImage gets cleared at the end
    }

    wxDELETEA(buffer);

    if(g_videoSetting.supportPBO || g_videoSetting.supportVBO)
    {
        g_canvas->rt->EndRender();

        // Clear RenderTexture object.
        g_canvas->rt->Shutdown();
        wxDELETE(g_canvas->rt);
    }

    // CREATE THE ACTUAL MULTI-IMAGE GIF ANIMATION
    // ------------------------------------------------------
    // Create the file and write all the data
    // Open/Create the file that were going to save to
    FILE *hFile = NULL;
    hFile = fopen(m_strFilename.fn_str(), "wb");

    // Set gif options
    CxImageGIF multiImage;
    multiImage.SetComment("Exported from WoW Model Viewer");
    if(m_bTransparent)
    {
        multiImage.SetDisposalMethod(2);
    }
    else
    {
        multiImage.SetDisposalMethod(0);
    }

    multiImage.SetFrameDelay(m_iDelay);
    multiImage.SetCodecOption(2); // LZW
    multiImage.SetLoops(0); // Set the animation to loop indefinately.

    // Create/Compose the animated gif
    multiImage.Encode(hFile, gifImages, m_iTotalFrames, false);

    // ALL DONE, START THE CLEAN UP
    // --------------------------------------------------------
    // Close file
    fclose(hFile);

    // Free the memory used by all the images to create the GIF
    for(unsigned int i = 0; i < m_iTotalFrames; i++)
    {
        gifImages[i]->Destroy();
        wxDELETE(gifImages[i]);
    }
    wxDELETEA(gifImages);

    // Free memory used by the colour palette
    if(m_pPal)
    {
        free(m_pPal);
        m_pPal = NULL;
    }

    wxLogMessage(_T("Info: GIF Animation successfully created.") );

    g_canvas->model->animManager->SetSpeed(m_fAnimSpeed); 
        // Return the animation speed back to whatever it was previously set as
    g_canvas->model->animManager->Play();

    Show(false);

    g_videoSetting.render = true;
    g_canvas->InitView();
}