⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gifexporter.cpp

📁 wowmodelview魔兽世界的模型查看工具。下了看看吧
💻 CPP
字号:

#include "gifexporter.h"
#include "Quantize.h"

enum {
	ID_GIFFRAME = 3500,
	ID_GIFSTART,
	ID_GIFEXIT,
	ID_GIFFILENAME,
	ID_GIFCURFRAME,
	ID_GIFTOTALFRAME,
	ID_GIFTRANSPARENT,
	ID_GIFDIFFUSE,
	ID_GIFSHRINK,
	ID_GIFGREYSCALE
};


IMPLEMENT_CLASS(GifExporter, wxFrame)

BEGIN_EVENT_TABLE(GifExporter, wxFrame)
	EVT_BUTTON(ID_GIFSTART, GifExporter::OnButton)
	EVT_BUTTON(ID_GIFEXIT, GifExporter::OnButton)

	EVT_CHECKBOX(ID_GIFTRANSPARENT, GifExporter::OnCheck)
	EVT_CHECKBOX(ID_GIFDIFFUSE, GifExporter::OnCheck)
	EVT_CHECKBOX(ID_GIFSHRINK, GifExporter::OnCheck)
	EVT_CHECKBOX(ID_GIFGREYSCALE, GifExporter::OnCheck)
END_EVENT_TABLE()

// This creates our frame and all our objects
GifExporter::GifExporter(ModelCanvas *c, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString fn)
{
	canvas = c;
	canvas->model->animManager->Pause(true);
	canvas->model->animManager->Stop();
	//canvas->model->animManager->AnimateParticles();

	GifImages = NULL;
	ppal = NULL;

	Transparent = false;
	Diffuse = false;
	Shrink = false;
	Greyscale = false;

	newWidth = 0;
	newHeight = 0;
			
	TotalAnimFrames = canvas->model->animManager->GetFrameCount();
	Filename = fn;

	if (Create(parent, id, title, pos, size, style, _T("GifExporterFrame")) == false) {
		wxMessageBox("Failed to create our Animated Gif Exporter window!", "Error");
		return;
	}
	
	wxStaticText *lblFile = new wxStaticText(this, -1, fn, wxPoint(10,5), wxSize(320,20));
	//lblCurFrame = new wxStaticText(this, -1, _T("Current Frame: 0"), wxPoint(10,25), wxSize(100,20));
	
	wxStaticText *lblTotalFrame = new wxStaticText(this, -1, _T("Total Frames:"), wxPoint(10,45), wxDefaultSize);
	txtFrames = new wxTextCtrl(this, ID_GIFTOTALFRAME, "", wxPoint(90,45), wxSize(30,18));
	int i = (TotalAnimFrames / 50);
	//float f = (TotalAnimFrames / 50);
	*txtFrames << i;
	
	cbTrans = new wxCheckBox(this, ID_GIFTRANSPARENT, _T("Transparency"), wxPoint(10,65), wxDefaultSize, 0);
	cbGrey = new wxCheckBox(this, ID_GIFGREYSCALE, _T("Greyscale"), wxPoint(130,65), wxDefaultSize, 0);
	cbDither = new wxCheckBox(this, ID_GIFDIFFUSE, _T("Error Diffusion"), wxPoint(10,85), wxDefaultSize, 0);
	cbShrink = new wxCheckBox(this, ID_GIFSHRINK, _T("Resize"), wxPoint(130,85), wxDefaultSize, 0);

	wxStaticText *lblSize = new wxStaticText(this, -1, _T("Size Dimensions:"), wxPoint(10,105), wxDefaultSize);
	txtSizeX = new wxTextCtrl(this, -1, _T("0"), wxPoint(100,105), wxSize(30,18));
	txtSizeX->Enable(false);
	txtSizeY = new wxTextCtrl(this, -1, _T("0"), wxPoint(140,105), wxSize(30,18));
	txtSizeY->Enable(false);

	wxStaticText *lblDelay = new wxStaticText(this, -1, _T("Gif Frame Delay: (1-100)"), wxPoint(10,128), wxDefaultSize);
	txtDelay = new wxTextCtrl(this, -1, _T("5"), wxPoint(140,125), wxSize(30,18));
	
	btnStart = new wxButton(this, ID_GIFSTART, _T("Start"), wxPoint(10,155), wxSize(62,26));
	btnCancel = new wxButton(this, ID_GIFEXIT, _T("Cancel"), wxPoint(80,155), wxSize(62,26));
}

GifExporter::~GifExporter()
{
	GifImages = NULL;
	ppal = NULL;
	canvas = NULL;
}


// This must be called before any frame-saving is attempted.
void GifExporter::BeginSaving()
{
	wxString(txtFrames->GetValue()).ToLong((long*)&TotalFrames);
	wxString(txtDelay->GetValue()).ToLong(&Delay);

	if (Delay < 1)
		Delay = 1;
	if (Delay > 100)
		Delay = 100;

	glReadBuffer(GL_BACK);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	
	int screenSize[4];
	glGetIntegerv(GL_VIEWPORT, screenSize);				// get the width/height of the canvas
	Width = screenSize[2];
	Height = screenSize[3];

	if (Shrink) {
		wxString(txtSizeX->GetValue()).ToLong(&newWidth);
		wxString(txtSizeY->GetValue()).ToLong(&newHeight);
		if (newWidth < 16 || newHeight < 16) {
			//Shrink = false;
			newWidth = Width / 2;
			newHeight = Height / 2;
		}
	}

	// will crash program - prevent this from happening
	if (TotalFrames > TotalAnimFrames) {
		wxMessageBox(_T("Impossible to make a gif with more frames than the model animation.\nClosing gif exporter."), _T("Error"));
		this->Destroy();
		return;
	}
	
	CurFrame = 0;
	
	// Stop our animation
	canvas->model->animManager->Pause(true);
	canvas->model->animManager->Stop();
	//canvas->model->animManager->AnimateParticles();

	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);

	TimeStep = (TotalAnimFrames / TotalFrames);

	size = Width*Height*4;	// (width*height*bytesPerPixel)	

	// Create one frame to make an optimum colour palette from.
	unsigned char *buffer = new unsigned char[size];
	glReadPixels(0, 0, Width, Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer);

	CxImage *newImage = new CxImage(0);
	newImage->CreateFromArray(buffer, Width, Height, 32, (Width*4), false);

#ifdef _WIN32
	if (Greyscale)
		newImage->GrayScale();
#endif

	if(Shrink)
		newImage->Resample(newWidth, newHeight, 2);
	
	// if (Optimise) {
	CQuantizer q(256, 8);
	q.ProcessImage((HANDLE)newImage->GetDIB());
	ppal = (RGBQUAD*) calloc(256*sizeof(RGBQUAD), 1); //This creates our gifs optimised global colour palette
	q.SetColorTable(ppal);
	// }
	
	delete newImage;
	delete buffer;
	// --

	GifImages = new CxImage*[TotalFrames];

	canvas->bSaving = true;
}

void GifExporter::SaveFrame()
{
	unsigned char *buffer = NULL;
	
	//wxString tmp("Current Frame: " + wxString::Format("%i", CurFrame));
	//lblCurFrame->SetLabel(tmp);
	
	buffer = new unsigned char[size];
	glReadPixels(0, 0, Width, Height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer);

	//
	CxImage *newImage = new CxImage(0);
	newImage->CreateFromArray(buffer, Width, Height, 32, (Width*4), false);

#ifdef _WIN32
	if (Greyscale)
		newImage->GrayScale();
#endif

	if(Shrink)
		newImage->Resample(newWidth, newHeight, 2);
	
	// if (Optimise) {
		newImage->DecreaseBpp(8, Diffuse, ppal, 256);
	// } else {
	//	newImage->DecreaseBpp(8, Diffuse, 0);
	// }
	
	newImage->SetCodecOption(2); // for LZW compression
	
	if(Transparent)
		newImage->SetTransIndex(newImage->GetPixelIndex(0,0));
	
	newImage->SetFrameDelay(Delay);
	GifImages[CurFrame] = newImage;

	CurFrame++;

	delete buffer;

	if (CurFrame >= TotalFrames) {
		EndSaving();
	}
}

void GifExporter::EndSaving()
{
	FILE* hFile;
	hFile = fopen(Filename.fn_str(), "wb");

	CxImageGIF multiimage;
	multiimage.SetComment("Exported from WoW Model Viewer");
	if (Transparent)
		multiimage.SetDisposalMethod(2);
	else
		multiimage.SetDisposalMethod(0);

	//multiimage.SetFrameDelay(Delay);
	multiimage.SetCodecOption(2); // LZW
	multiimage.Encode(hFile, GifImages, TotalFrames, false);

	fclose(hFile);

	for(int i=0; i<TotalFrames; i++)
	{
		GifImages[i]->Destroy();
		delete GifImages[i];
	}
	delete [] GifImages;

	canvas->bSaving = false;

	if (ppal) 
		free(ppal);

	this->Show(false);
	//wxMessageBox("Animation successfully exported!", "Gif Export");

	//canvas->animManager.Stop();
	canvas->model->animManager->Play();

	this->Destroy();
}

void GifExporter::OnButton(wxCommandEvent &event)
{
	if (event.GetId() == ID_GIFSTART){
		this->Show(false);
		this->Refresh();
		BeginSaving();
	} else if (event.GetId() == ID_GIFEXIT) {
		this->Destroy();
	}
}

void GifExporter::OnCheck(wxCommandEvent &event)
{
	if (event.GetId() == ID_GIFTRANSPARENT) {
		Transparent = event.IsChecked();
	} else if (event.GetId() == ID_GIFDIFFUSE) {
		Diffuse = event.IsChecked();
	} else if (event.GetId() == ID_GIFSHRINK) {
		Shrink = event.IsChecked();
		txtSizeX->Enable(Shrink);
		txtSizeY->Enable(Shrink);
		if (Shrink) {
			int screenSize[4];
			glGetIntegerv(GL_VIEWPORT, screenSize);				// get the width/height of the canvas
			txtSizeX->Clear();
			*txtSizeX << screenSize[2];
			txtSizeY->Clear();
			*txtSizeY << screenSize[3];
		}
		
	} else if (event.GetId() == ID_GIFGREYSCALE) {
		Greyscale = event.IsChecked();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -