From 1a3e88eda8fb9a711f4eb47112babc27e8c153ac Mon Sep 17 00:00:00 2001 From: Anurag Aggarwal Date: Thu, 9 Jul 2020 12:58:26 +0530 Subject: [PATCH 1/2] Batch rendering --- src/include/xmenu.h | 14 +++++++ src/ui-hlp/menu.cpp | 81 ++++++++++++++++++++++++++++++++++++++++- src/ui/customdialog.cpp | 39 ++++++++++++++++++++ src/ui/customdialog.h | 4 ++ 4 files changed, 136 insertions(+), 2 deletions(-) diff --git a/src/include/xmenu.h b/src/include/xmenu.h index 9348804e..e906773b 100644 --- a/src/include/xmenu.h +++ b/src/include/xmenu.h @@ -32,6 +32,7 @@ typedef char *(*tokenfunc)(struct uih_context *c); #define DIALOG_ONOFF 8 #define DIALOG_COORD 9 #define DIALOG_PALSLIDER 10 +#define DIALOG_IFILES 11 #define DIALOGIFILE(question, filename) \ { \ @@ -73,6 +74,10 @@ typedef char *(*tokenfunc)(struct uih_context *c); { \ question, DIALOG_SLIDER, default \ } +#define DIALOGIFILES(question, filenames) \ + { \ + question, DIALOG_IFILES, 0, filenames \ + } #define DIALOGIFILE_I(_question, _filename) \ menudialogs_i18n[no_menudialogs_i18n].question = _question; \ @@ -146,6 +151,15 @@ typedef char *(*tokenfunc)(struct uih_context *c); menudialogs_i18n[no_menudialogs_i18n].defint = _default; \ ++no_menudialogs_i18n; +#define DIALOGIFILES_I(_question, _filenames) \ + menudialogs_i18n[no_menudialogs_i18n].question = _question; \ + menudialogs_i18n[no_menudialogs_i18n].type = DIALOG_IFILES; \ + menudialogs_i18n[no_menudialogs_i18n].defint = 0; \ + menudialogs_i18n[no_menudialogs_i18n].defstr = _filenames; \ + menudialogs_i18n[no_menudialogs_i18n].deffloat = 0; \ + menudialogs_i18n[no_menudialogs_i18n].deffloat2 = 0; \ + ++no_menudialogs_i18n; + #define NULL_I() \ menudialogs_i18n[no_menudialogs_i18n].question = NULL; \ menudialogs_i18n[no_menudialogs_i18n].type = 0; \ diff --git a/src/ui-hlp/menu.cpp b/src/ui-hlp/menu.cpp index 488f305a..04aedc83 100644 --- a/src/ui-hlp/menu.cpp +++ b/src/ui-hlp/menu.cpp @@ -13,6 +13,7 @@ #include "play.h" #include "i18n.h" #include "xthread.h" +#include "customdialog.h" #define LANG(name, name2) \ MENUSTRING("lang", NULL, name, name2, 0, \ @@ -62,7 +63,7 @@ const char *const uih_colornames[] = {"white", "black", "red", NULL}; * Zoltan Kovacs , 2003-01-05 */ -#define MAX_MENUDIALOGS_I18N 104 +#define MAX_MENUDIALOGS_I18N 115 #define Register(variable) variable = &menudialogs_i18n[no_menudialogs_i18n] static menudialog menudialogs_i18n[MAX_MENUDIALOGS_I18N]; // static int no_menudialogs_i18n; @@ -76,7 +77,8 @@ static menudialog *uih_perturbationdialog, *uih_juliadialog, *uih_filterdialog, *uih_shiftdialog, *uih_speeddialog, *printdialog, *uih_bailoutdialog, *uih_threaddialog, *saveanimdialog, *uih_juliamodedialog, *uih_textposdialog, *uih_fastmodedialog, *uih_timedialog, *uih_numdialog, - *uih_fpdialog, *palettedialog, *uih_cyclingdialog, *loadimgdialog, *palettegradientdialog + *uih_fpdialog, *palettedialog, *uih_cyclingdialog, *loadimgdialog, *palettegradientdialog, + *uih_batchrenderdialog #ifdef USE_SFFE , *uih_sffedialog, *uih_sffeinitdialog @@ -128,6 +130,19 @@ void uih_registermenudialogs_i18n(void) DIALOGCHOICE_I(TR("Dialog", "Always recalculate:"), yesno, 0); NULL_I(); + Register(uih_batchrenderdialog); + DIALOGIFILES_I(TR("Dialog", "Files to render:"), NULL); + DIALOGOFILE_I(TR("Dialog", "Basename:"), "anim"); + DIALOGINT_I(TR("Dialog", "Width:"), 640); + DIALOGINT_I(TR("Dialog", "Height:"), 480); + DIALOGFLOAT_I(TR("Dialog", "Pixel width (cm):"), 0.025); + DIALOGFLOAT_I(TR("Dialog", "Pixel height (cm):"), 0.025); + DIALOGFLOAT_I(TR("Dialog", "Framerate:"), 30); + DIALOGCHOICE_I(TR("Dialog", "Image type:"), imgtypes, 0); + DIALOGCHOICE_I(TR("Dialog", "Antialiasing:"), yesno, 0); + DIALOGCHOICE_I(TR("Dialog", "Always recalculate:"), yesno, 0); + NULL_I(); + Register(uih_viewdialog); DIALOGCOORD_I(TR("Dialog", "Center:"), 0, 0); DIALOGFLOAT_I(TR("Dialog", "Radius:"), 1); @@ -380,6 +395,65 @@ static void uih_render(struct uih_context *c, dialogparam *d) d[8].dint, d[9].dint, c->letterspersec, NULL); } +static void uih_batchrender(struct uih_context *c, dialogparam *d) +{ + if(fnames.isEmpty()) { + uih_error(c, "No file Selected"); + return; + } + if (d[2].dint <= 0 || d[2].dint > 4096) { + uih_error( + c, + TR("Error", + "renderanim: Width parameter must be positive integer in the range 0..4096")); + return; + } + if (d[3].dint <= 0 || d[3].dint > 4096) { + uih_error( + c, + TR("Error", + "renderanim: Height parameter must be positive integer in the range 0..4096")); + return; + } + if (d[4].number <= 0 || d[5].number <= 0) { + uih_error(c, + TR("Error", + "renderanim: Invalid real width and height dimensions")); + return; + } + if (d[6].number <= 0 || d[6].number >= 1000000) { + uih_error(c, TR("Error", "renderanim: invalid framerate")); + return; + } + if (d[7].dint && d[8].dint) { + uih_error( + c, TR("Error", + "renderanim: antialiasing not supported in 256 color mode")); + return; + } + for(int i=0; i < (int)fnames.size(); i++) { + QString hlpmsg = "Rendering (" + QString::number(i) + "/" + + QString::number(fnames.size()) + ") " + fnames[i]; + uih_message(c, hlpmsg.toStdString().c_str()); + char* curr_file = strdup(fnames[i].toStdString().c_str()); + char* base_name = strdup(d[1].dstring); + QString file_number = "_" + QString::number(i) + "_"; + strcat(base_name, file_number.toStdString().c_str()); + + uih_renderanimation(c, base_name, (xio_path)curr_file, d[2].dint, + d[3].dint, d[4].number, d[5].number, + (int)(1000000 / d[6].number), + #ifdef STRUECOLOR24 + d[7].dint ? C256 : TRUECOLOR24, + #else + d[7].dint ? C256 : TRUECOLOR, + #endif + d[8].dint, d[9].dint, c->letterspersec, NULL); + } +} + + + static menudialog *uih_getcolordialog(struct uih_context *c) { if (c != NULL) { @@ -1037,8 +1111,11 @@ void uih_registermenus_i18n(void) MENUFLAG_INTERRUPT, uih_loadpngfile, loadimgdialog); MENUDIALOG_I("file", NULL, TR("Menu", "Save image"), "saveimg", 0, uih_savepngfile, saveimgdialog); + MENUSEPARATOR_I("file"); MENUDIALOG_I("file", NULL, TR("Menu", "Render"), "renderanim", UI, uih_render, uih_renderdialog); + MENUDIALOG_I("file", NULL, TR("Menu", "Batch Render"), "batchrender", UI, + uih_batchrender, uih_batchrenderdialog); MENUSEPARATOR_I("file"); MENUNOP_I("file", NULL, TR("Menu", "Load random example"), "loadexample", MENUFLAG_INTERRUPT, uih_loadexample); diff --git a/src/ui/customdialog.cpp b/src/ui/customdialog.cpp index cb21a3be..83c8479a 100644 --- a/src/ui/customdialog.cpp +++ b/src/ui/customdialog.cpp @@ -14,6 +14,8 @@ #include #endif +QStringList fnames = {}; + QString format(number_t number) { char buf[256]; @@ -93,6 +95,27 @@ CustomDialog::CustomDialog(struct uih_context *uih, const menuitem *item, formLayout->addRow(label, layout); + } else if (dialog[i].type == DIALOG_IFILES) { + + QLineEdit *filename = new QLineEdit(dialog[i].defstr, this); + QFontMetrics metric(filename->font()); + filename->setMinimumWidth(metric.width(filename->text()) * 1.1); + filename->setObjectName(label); + + + QToolButton *chooser = new QToolButton(this); + chooser->setObjectName(label); + chooser->setText("..."); + connect(chooser, SIGNAL(clicked()), this, + SLOT(chooseInputFiles())); + + QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(filename); + layout->addWidget(chooser); + + formLayout->addRow(label, layout); + } else if (dialog[i].type == DIALOG_CHOICE) { QComboBox *combo = new QComboBox(this); @@ -224,6 +247,9 @@ void CustomDialog::accept() QComboBox *field = findChild(label); m_parameters[i].dint = field->currentIndex(); + } + else if (m_dialog[i].type == DIALOG_IFILES){ + m_parameters[i].dstring = (char* )malloc(sizeof(char)); // FIXME Prevents mem leak } else { QLineEdit *field = findChild(label); @@ -278,6 +304,19 @@ void CustomDialog::chooseOutputFile() } } +void CustomDialog::chooseInputFiles() +{ + QLineEdit *field = findChild(sender()->objectName()); + QSettings settings; + QString fileLocation = settings.value("MainWindow/lastFileLocation", QDir::homePath()).toString(); + fnames = QFileDialog::getOpenFileNames( + this, sender()->objectName(), fileLocation, "*.xpf *.xaf"); + if(!fnames.isEmpty()) { + field->setText(QString::number(fnames.size())); + settings.setValue("MainWindow/lastFileLocation", QFileInfo(fnames[0]).absolutePath()); + } +} + void CustomDialog::updateVisualiser() { // Get updated Colors diff --git a/src/ui/customdialog.h b/src/ui/customdialog.h index b9d2fbe1..c069bb78 100644 --- a/src/ui/customdialog.h +++ b/src/ui/customdialog.h @@ -7,6 +7,9 @@ #include #include "ui.h" + +extern QStringList fnames; + class CustomDialog : public QDialog { Q_OBJECT @@ -21,6 +24,7 @@ class CustomDialog : public QDialog QSlider *seedslider, *algoslider, *shiftslider; private slots: void chooseInputFile(); + void chooseInputFiles(); void chooseOutputFile(); void updateVisualiser(); From 5776abfa53d4131d278a7864fd7fccec1a1ccc2a Mon Sep 17 00:00:00 2001 From: Anurag Aggarwal Date: Thu, 9 Jul 2020 13:28:42 +0530 Subject: [PATCH 2/2] avoid mem leak --- src/ui-hlp/menu.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ui-hlp/menu.cpp b/src/ui-hlp/menu.cpp index 04aedc83..a7c8b1db 100644 --- a/src/ui-hlp/menu.cpp +++ b/src/ui-hlp/menu.cpp @@ -436,9 +436,12 @@ static void uih_batchrender(struct uih_context *c, dialogparam *d) QString::number(fnames.size()) + ") " + fnames[i]; uih_message(c, hlpmsg.toStdString().c_str()); char* curr_file = strdup(fnames[i].toStdString().c_str()); - char* base_name = strdup(d[1].dstring); + strdup(d[1].dstring); QString file_number = "_" + QString::number(i) + "_"; - strcat(base_name, file_number.toStdString().c_str()); + char* file_suffix = strdup(file_number.toStdString().c_str()); + char* base_name = (char *)malloc(strlen(d[1].dstring) + strlen(file_suffix) + 2); + strcpy(base_name, d[1].dstring); + strcat(base_name, file_suffix); uih_renderanimation(c, base_name, (xio_path)curr_file, d[2].dint, d[3].dint, d[4].number, d[5].number, @@ -449,6 +452,7 @@ static void uih_batchrender(struct uih_context *c, dialogparam *d) d[7].dint ? C256 : TRUECOLOR, #endif d[8].dint, d[9].dint, c->letterspersec, NULL); + free(base_name); } }