📄 gifexporter.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 + -