浏览代码

wxGUI/animation: fix export (run as background thread) output animation file to avi format (#840)

Tomas Zigo 4 年之前
父节点
当前提交
a4fd41e86c
共有 2 个文件被更改,包括 51 次插入17 次删除
  1. 23 8
      gui/wxpython/animation/controller.py
  2. 28 9
      lib/python/imaging/images2avi.py

+ 23 - 8
gui/wxpython/animation/controller.py

@@ -18,6 +18,7 @@ import wx
 
 
 from core.gcmd import GException, GError, GMessage
 from core.gcmd import GException, GError, GMessage
 from grass.imaging import writeAvi, writeGif, writeIms, writeSwf
 from grass.imaging import writeAvi, writeGif, writeIms, writeSwf
+from core.gthread import gThread
 from core.settings import UserSettings
 from core.settings import UserSettings
 from gui_core.wrap import EmptyImage, ImageFromBitmap
 from gui_core.wrap import EmptyImage, ImageFromBitmap
 
 
@@ -619,10 +620,17 @@ class AnimationController(wx.EvtHandler):
 
 
         # export
         # export
         pilImages = [WxImageToPil(image) for image in images]
         pilImages = [WxImageToPil(image) for image in images]
-        busy = wx.BusyInfo(_("Exporting animation, please wait..."),
-                           parent=self.frame)
+        self.busy = wx.BusyInfo(_("Exporting animation, please wait..."),
+                                parent=self.frame)
         wx.GetApp().Yield()
         wx.GetApp().Yield()
         try:
         try:
+            def export_avi_callback(event):
+                error = event.ret
+                del self.busy
+                if error:
+                    GError(parent=self.frame, message=error)
+                    return
+
             if exportInfo['method'] == 'sequence':
             if exportInfo['method'] == 'sequence':
                 filename = os.path.join(
                 filename = os.path.join(
                     exportInfo['directory'],
                     exportInfo['directory'],
@@ -637,12 +645,19 @@ class AnimationController(wx.EvtHandler):
                 writeSwf(filename=exportInfo['file'], images=pilImages,
                 writeSwf(filename=exportInfo['file'], images=pilImages,
                          duration=self.timeTick / float(1000), repeat=True)
                          duration=self.timeTick / float(1000), repeat=True)
             elif exportInfo['method'] == 'avi':
             elif exportInfo['method'] == 'avi':
-                writeAvi(filename=exportInfo['file'], images=pilImages,
-                         duration=self.timeTick / float(1000),
-                         encoding=exportInfo['encoding'],
-                         inputOptions=exportInfo['options'])
+                thread = gThread()
+                thread.Run(callable=writeAvi,
+                           filename=exportInfo['file'],
+                           images=pilImages,
+                           duration=self.timeTick / float(1000),
+                           encoding=exportInfo['encoding'],
+                           inputOptions=exportInfo['options'],
+                           bg_task=True,
+                           ondone=export_avi_callback,
+                )
         except Exception as e:
         except Exception as e:
-            del busy
+            del self.busy
             GError(parent=self.frame, message=str(e))
             GError(parent=self.frame, message=str(e))
             return
             return
-        del busy
+        if exportInfo['method'] in ('sequence', 'gif', 'swf'):
+            del self.busy

+ 28 - 9
lib/python/imaging/images2avi.py

@@ -42,7 +42,9 @@ import os
 import time
 import time
 import subprocess
 import subprocess
 import shutil
 import shutil
+
 from grass.imaging import images2ims
 from grass.imaging import images2ims
+import grass.script as gscript
 
 
 
 
 def _cleanDir(tempDir):
 def _cleanDir(tempDir):
@@ -58,7 +60,7 @@ def _cleanDir(tempDir):
 
 
 
 
 def writeAvi(filename, images, duration=0.1, encoding='mpeg4',
 def writeAvi(filename, images, duration=0.1, encoding='mpeg4',
-             inputOptions='', outputOptions=''):
+             inputOptions='', outputOptions='', bg_task=False):
     """Export movie to a AVI file, which is encoded with the given
     """Export movie to a AVI file, which is encoded with the given
     encoding. Hint for Windows users: the 'msmpeg4v2' codec is
     encoding. Hint for Windows users: the 'msmpeg4v2' codec is
     natively supported on Windows.
     natively supported on Windows.
@@ -77,13 +79,17 @@ def writeAvi(filename, images, duration=0.1, encoding='mpeg4',
     :param str encoding: the encoding type
     :param str encoding: the encoding type
     :param inputOptions:
     :param inputOptions:
     :param outputOptions:
     :param outputOptions:
+    :param bool bg_task: if thread background task, not raise but
+    return error message
+
+    :return str: error message
     """
     """
 
 
     # Get fps
     # Get fps
     try:
     try:
-        fps = float(1.0/duration)
+        fps = float(1.0 / duration)
     except Exception:
     except Exception:
-        raise ValueError("Invalid duration parameter for writeAvi.")
+        raise ValueError(_('Invalid duration parameter for writeAvi.'))
 
 
     # Determine temp dir and create images
     # Determine temp dir and create images
     tempDir = os.path.join(os.path.expanduser('~'), '.tempIms')
     tempDir = os.path.join(os.path.expanduser('~'), '.tempIms')
@@ -113,15 +119,28 @@ def writeAvi(filename, images, duration=0.1, encoding='mpeg4',
     outPut = S.stdout.read()
     outPut = S.stdout.read()
 
 
     if S.wait():
     if S.wait():
-        # An error occurred, show
-        print(outPut)
-        print(S.stderr.read())
         # Clean up
         # Clean up
         _cleanDir(tempDir)
         _cleanDir(tempDir)
-        raise RuntimeError("Could not write avi.")
+        if bg_task:
+            return gscript.decode(outPut) + '\n' + gscript.decode(
+                S.stderr.read()) + '\n' + _('Could not write avi.')
+        else:
+            # An error occurred, show
+            print(gscript.decode(outPut))
+            print(gscript.decode(S.stderr.read()))
+            raise RuntimeError(_('Could not write avi.'))
     else:
     else:
-        # Copy avi
-        shutil.copy(os.path.join(tempDir, 'output.avi'), filename)
+        try:
+            # Copy avi
+            shutil.copy(os.path.join(tempDir, 'output.avi'), filename)
+        except Exception as err:
+            # Clean up
+            _cleanDir(tempDir)
+            if bg_task:
+                return str(err)
+            else:
+                raise
+
         # Clean up
         # Clean up
         _cleanDir(tempDir)
         _cleanDir(tempDir)