]> SALOME platform Git repositories - modules/visu.git/commitdiff
Salome HOME
Generate AVI on animation
authorapo <apo@opencascade.com>
Tue, 11 Apr 2006 11:39:29 +0000 (11:39 +0000)
committerapo <apo@opencascade.com>
Tue, 11 Apr 2006 11:39:29 +0000 (11:39 +0000)
src/VISUGUI/VisuGUI_TimeAnimation.cxx
src/VISUGUI/VisuGUI_TimeAnimation.h
src/VISU_I/VISU_TimeAnimation.cxx
src/VISU_I/VISU_TimeAnimation.h

index 3ac37f5f28ce0747f55923a6de2c429a0a23e6bb..b8afb4e9f136f7245010e3735160621e55301710 100644 (file)
@@ -1093,6 +1093,8 @@ VisuGUI_TimeAnimationDlg::VisuGUI_TimeAnimationDlg (VisuGUI* theModule, _PTR(Stu
   aSaveLay->setMargin( 5 );
 
   mySaveCheck = new QCheckBox("Save pictures to directory", aSaveBox);
+  connect(mySaveCheck, SIGNAL( toggled(bool)),
+          this, SLOT( onCheckDump(bool) ));
   aSaveLay->addMultiCellWidget(mySaveCheck, 0, 0, 0, 2);
 
   QLabel* aFormatLbl = new QLabel("Saving format:", aSaveBox);
@@ -1137,6 +1139,35 @@ VisuGUI_TimeAnimationDlg::VisuGUI_TimeAnimationDlg (VisuGUI* theModule, _PTR(Stu
   mySaveCheck->setChecked(false);
   aSaveLay->addWidget(aBrowseBtn, 2, 2);
 
+  mySaveAVICheck = new QCheckBox("Save animation to AVI file", aSaveBox);
+  connect(mySaveAVICheck, SIGNAL( toggled(bool)),
+          this, SLOT( onCheckDump(bool) ));
+  aSaveLay->addMultiCellWidget(mySaveAVICheck, 3, 3, 0, 2);
+
+  QLabel* aPathAVILbl = new QLabel("Path:", aSaveBox);
+  aPathAVILbl->setEnabled(false);
+  connect(mySaveAVICheck, SIGNAL( toggled(bool)),
+          aPathAVILbl, SLOT( setEnabled(bool) ));
+  aSaveLay->addWidget(aPathAVILbl, 4, 0);
+
+  myPathAVIEdit = new QLineEdit(aSaveBox);
+  myPathAVIEdit->setReadOnly(true);
+  myPathAVIEdit->setEnabled(false);
+  connect(mySaveAVICheck, SIGNAL( toggled(bool)),
+          myPathAVIEdit, SLOT( setEnabled(bool) ));
+  aSaveLay->addWidget(myPathAVIEdit, 4, 1);
+
+  QPushButton* aBrowseAVIBtn = new QPushButton("Browse...", aSaveBox);
+  aBrowseAVIBtn->setEnabled(false);
+  connect(mySaveAVICheck, SIGNAL( toggled(bool)),
+         aBrowseAVIBtn, SLOT( setEnabled(bool) ));
+  connect(aBrowseAVIBtn, SIGNAL( clicked()),
+         this, SLOT( onBrowseAVI() ));
+  aSaveLay->addWidget(aBrowseAVIBtn, 4, 2);
+
+  mySaveAVICheck->setChecked(false);
+  mySaveAVICheck->setEnabled(myAnimator->checkAVIMaker());
+
   TopLayout->addMultiCellWidget(aSaveBox, 7, 7, 0, 3);
 
   aMainLayout->addWidget(myPlayFrame);
@@ -1245,6 +1276,9 @@ void VisuGUI_TimeAnimationDlg::onPlayPressed()
       QStrList aDumpFormats = QImageIO::outputFormats();
       myAnimator->setDumpFormat(aDumpFormats.at(myPicsFormat->currentItem()));
       myAnimator->dumpTo(myPathEdit->text());
+    } else if (mySaveAVICheck->isChecked()) {
+      myAnimator->setDumpFormat("AVI");
+      myAnimator->dumpTo(myPathAVIEdit->text());
     } else {
       myAnimator->dumpTo("");
     }
@@ -1369,11 +1403,44 @@ void VisuGUI_TimeAnimationDlg::onSetupDlg()
 //------------------------------------------------------------------------
 void VisuGUI_TimeAnimationDlg::onBrowse()
 {
-  QString aPath = SUIT_FileDlg::getExistingDirectory(this, "/", "Select path");
+  //  QString aPath = SUIT_FileDlg::getExistingDirectory(this, "/", "Select path");
+  QString aPath = SUIT_FileDlg::getExistingDirectory(this, getenv("HOME"), "Select path");
   if (!aPath.isEmpty())
     myPathEdit->setText(Qtx::addSlash(aPath));
 }
 
+//------------------------------------------------------------------------
+void VisuGUI_TimeAnimationDlg::onBrowseAVI()
+{
+  QStringList aFilter;
+  aFilter.append( "AVI Files (*.avi)" );
+  aFilter.append( "All Files (*.*)" );
+
+  QString aPath = SUIT_FileDlg::getFileName(this, getenv("HOME"), aFilter, "Select file", false);
+  if (!aPath.isEmpty())
+    myPathAVIEdit->setText(aPath);
+}
+
+//------------------------------------------------------------------------
+void VisuGUI_TimeAnimationDlg::onCheckDump(bool)
+{
+  const QObject* source = sender();
+  if (source == mySaveCheck) {
+    if (mySaveCheck->isChecked()) {
+      if (mySaveAVICheck->isChecked())
+       mySaveAVICheck->setChecked(false);
+    }
+    mySaveAVICheck->setEnabled(!mySaveCheck->isChecked());
+  }
+  else if (source == mySaveAVICheck) {
+    if (mySaveAVICheck->isChecked()) {
+      if (mySaveCheck->isChecked())
+       mySaveCheck->setChecked(false);
+    }
+    mySaveCheck->setEnabled(!mySaveAVICheck->isChecked());
+  }
+}
+
 //------------------------------------------------------------------------
 void VisuGUI_TimeAnimationDlg::onStop()
 {
index 3b6d60990cd2e51127890db0f2c797cc06db0fb5..ec35e0d2abe14b3fd53008a890eaa4ee0db2d44b 100644 (file)
@@ -157,6 +157,8 @@ class VisuGUI_TimeAnimationDlg: public QDialog
    void onSpeedChange(double theSpeed);
    void onExecution(long theNewFrame, double theTime);
    void onBrowse();
+   void onBrowseAVI();
+   void onCheckDump(bool);
    void onStop();
    void onHelp();
    void saveToStudy();
@@ -183,6 +185,9 @@ class VisuGUI_TimeAnimationDlg: public QDialog
     bool isClosing;
     QCloseEvent* myEvent;
 
+    QCheckBox* mySaveAVICheck;
+    QLineEdit* myPathAVIEdit;
+
     QPushButton* myPublishBtn;
     QPushButton* mySaveBtn;
 };
index ce6025333ff8b6dbe346862a62200e78bc52bdc3..432404e09e2554e491791786bf67955cae6860f1 100644 (file)
@@ -47,6 +47,7 @@
 #include <qpixmap.h>
 #include <qimage.h>
 #include <qstrlist.h>
+#include <qdir.h>
 
 using namespace std;
 
@@ -77,6 +78,9 @@ VISU_TimeAnimation::VISU_TimeAnimation (_PTR(Study) theStudy,
   myCycling = false;
 
   myAnimEntry = "";
+
+  myDumpPath = "";
+  myAVIMaker = "jpeg2yuv";
 }
 
 
@@ -562,6 +566,10 @@ void VISU_TimeAnimation::run()
   double aOneVal = 1;
   if (myFieldsLst[0].myNbFrames > 2)
     aOneVal = myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0];
+  myFileIndex = 0;
+  int aNbFiles = 0;
+  QValueList<int> anIndexList;
+
   qApp->lock();
   while (myIsActive) {
     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
@@ -610,15 +618,57 @@ void VISU_TimeAnimation::run()
       qApp->unlock();
       msleep(100);
       qApp->lock();
-      QString aFile(myDumpPath);
-      QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
-      int aPos = -1;
-      while ((aPos = aName.find(".")) > -1 )
-       aName.replace(aPos, 1, "_");
-      aFile += aName;
-      aFile += ".";
-      aFile += myDumpFormat.lower();
-      myView->dumpViewToFormat(aFile,myDumpFormat);
+      if (myDumpFormat.compare("AVI") != 0) {
+       QString aFile(myDumpPath);
+       QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
+       int aPos = -1;
+       while ((aPos = aName.find(".")) > -1 )
+         aName.replace(aPos, 1, "_");
+       aFile += aName;
+       aFile += ".";
+       aFile += myDumpFormat.lower();
+       myView->dumpViewToFormat(aFile,myDumpFormat);
+      } else {
+       QFileInfo aFileInfo(myDumpPath);
+       QString aDirPath = aFileInfo.dirPath(true);
+       QString aBaseName = aFileInfo.fileName();
+
+       switch (myFrame) {
+       case 0: 
+         break;
+       case 1:
+         myFileIndex += 5;
+         break;
+       default:
+         if (myProportional) {
+           double p = (myFieldsLst[0].myTiming[myFrame] -
+                       myFieldsLst[0].myTiming[myFrame-1]) / aOneVal;
+           myFileIndex += (long) (5*p);
+         } else {
+           myFileIndex += 5;
+         }
+       }
+
+       QString aFile = aDirPath + QDir::separator() + aBaseName;
+       aFile += "_";
+       aFile += QString("%1").arg(myFileIndex).rightJustify(8, '0');
+       aFile += ".jpeg";
+
+       /* check image size is divisable 16
+       myView->dumpViewToFormat(aFile,"JPEG");
+       */
+       SUIT_ViewWindow* aView = myView;
+       QImage img = aView->dumpView();
+       if (!img.isNull()) {
+         int width = img.width(); width = (width/16)*16;
+         int height = img.height(); height = (height/16)*16;
+         QImage copy = img.copy(0, 0, width, height);
+         if (copy.save(aFile, "JPEG")) {
+           anIndexList.append(myFileIndex);
+           aNbFiles++;
+         }
+       }
+      }
     }
 
     if (!myIsActive) break;
@@ -633,6 +683,58 @@ void VISU_TimeAnimation::run()
        myFrame = 0;
     }
   }
+
+  // make AVI file if need
+  if (isDumping && myDumpFormat.compare("AVI") == 0) {
+    double aFPS = 17.3 * mySpeed;
+
+    QFileInfo aFileInfo(myDumpPath);
+    QString aDirPath = aFileInfo.dirPath(true);
+    QString aBaseName = aFileInfo.fileName();
+
+    // add missing files
+    if (anIndexList.count() > 1) {
+      QString aFFile = aDirPath + QDir::separator() + aBaseName;
+      aFFile += QString("_%1.jpeg");
+      int aStartIndex = anIndexList[0], anEndIndex;
+      for (int i = 1; i < anIndexList.count(); i++) {
+       anEndIndex = anIndexList[i];
+       QString aCurFile = aFFile.arg(QString::number(aStartIndex).rightJustify(8, '0'));
+       QStringList aCommands;
+       for (int j = aStartIndex+1; j < anEndIndex; j++) {
+         QString aFile = aFFile.arg(QString::number(j).rightJustify(8, '0'));
+         aCommands.append(QString("ln -s %1 %2").arg(aCurFile).arg(aFile));
+       }
+       system(aCommands.join(" ; \\\n").latin1());
+       aStartIndex = anEndIndex;
+      }
+    }
+
+    // make AVI file
+    QString aPattern = aDirPath + QDir::separator() + aBaseName;
+    aPattern += "_\%08d.jpeg";
+
+    QString aCmd = myAVIMaker;
+    aCmd += " -I p";
+    aCmd += " -v 0";
+    aCmd += QString(" -f %1").arg(aFPS);
+    // aCmd += QString(" -n %1").arg(aNbFiles);
+    aCmd += QString(" -n %1").arg(myFileIndex+1);
+    aCmd += QString(" -j %1").arg(aPattern);
+    aCmd += " | yuv2lav";
+    aCmd += QString(" -o %1").arg(myDumpPath);
+    system(aCmd.latin1());
+
+    // remove temporary jpeg files
+    aCmd = "( ";
+    aCmd += QString("cd %1").arg(aDirPath);
+    aCmd += "; ls";
+    aCmd += QString(" | egrep '%1_[0-9]*.jpeg'").arg(aBaseName);
+    aCmd += " | xargs rm";
+    aCmd += " )";
+    system(aCmd.latin1());
+  }
+
   emit stopped();
   qApp->unlock();
   QThread::exit();
@@ -691,7 +793,8 @@ std::string VISU_TimeAnimation::setDumpFormat(const char* theFormat)
 {
   myDumpFormat = theFormat;
   QStrList aDumpFormats = QImageIO::outputFormats();
-  if (myDumpFormat.isEmpty() || aDumpFormats.find(theFormat) < 0) {
+  if (myDumpFormat.isEmpty() || 
+      (aDumpFormats.find(theFormat) < 0 && myDumpFormat.compare("AVI") != 0)) {
     if (aDumpFormats.find("JPEG"))
       myDumpFormat = "JPEG";
     else
@@ -700,6 +803,19 @@ std::string VISU_TimeAnimation::setDumpFormat(const char* theFormat)
   return myDumpFormat.latin1();
 }
 
+//------------------------------------------------------------------------
+bool VISU_TimeAnimation::checkAVIMaker() const
+{
+  QStrList aDumpFormats = QImageIO::outputFormats();
+  if (aDumpFormats.find("JPEG") < 0) return false;
+
+  QString aCmd("which ");
+  aCmd += myAVIMaker;
+  aCmd += " >& /dev/null";
+  int iErr = system(aCmd.latin1());
+  return (iErr == 0);
+}
+
 //************************************************************************
 int VISU_TimeAnimation::myNBAnimations = 0;
 QString VISU_TimeAnimation::GenerateName()
index a090a1db9abd0abaf3913fabfbe7d089f74d91d6..ea14a17a220812a952228fc030e7035d2a22fd24 100644 (file)
@@ -103,6 +103,7 @@ class VISU_TimeAnimation: public QObject, public QThread
 
   void dumpTo(const char* thePath) { myDumpPath = thePath; }
   std::string setDumpFormat(const char* theFormat);
+  bool checkAVIMaker() const;
 
   QString getLastErrorMsg() { return myLastError; }
 
@@ -150,6 +151,8 @@ class VISU_TimeAnimation: public QObject, public QThread
   double myTimeMin   , myTimeMax   ; //!< Range of time stams, available for animation
   QString myDumpPath;
   QString myDumpFormat;
+  QString myAVIMaker;
+  long myFileIndex;
   SVTK_ViewWindow* myView;
 
   QString myAnimEntry;