chiark / gitweb /
6046e4c5c356d22f19e5e90117babb97ba96b5f8
[cura.git] / Cura / gui / util / webcam.py
1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 import os
5 import glob
6 import subprocess
7 import platform
8
9 import wx
10
11 from Cura.util import profile
12 from Cura.util.resources import getPathForImage
13
14 try:
15         #Try to find the OpenCV library for video capture.
16         from opencv import cv
17         from opencv import highgui
18 except:
19         cv = None
20
21 try:
22         #Use the vidcap library directly from the VideoCapture package. (Windows only)
23         #       http://videocapture.sourceforge.net/
24         # We're using the binary interface, not the python interface, so we don't depend on PIL
25         import vidcap as win32vidcap
26 except:
27         win32vidcap = None
28
29 def hasWebcamSupport():
30         if cv == None and win32vidcap == None:
31                 return False
32         if not os.path.exists(getFFMPEGpath()):
33                 return False
34         return True
35
36
37 def getFFMPEGpath():
38         if platform.system() == "Windows":
39                 return os.path.normpath(os.path.join(os.path.split(__file__)[0], "../../ffmpeg.exe"))
40         elif os.path.exists('/usr/bin/ffmpeg'):
41                 return '/usr/bin/ffmpeg'
42         return os.path.normpath(os.path.join(os.path.split(__file__)[0], "../../ffmpeg"))
43
44
45 class webcam(object):
46         def __init__(self):
47                 self._cam = None
48                 self._overlayImage = wx.Bitmap(getPathForImage('cura-overlay.png'))
49                 self._overlayUltimaker = wx.Bitmap(getPathForImage('ultimaker-overlay.png'))
50                 if cv != None:
51                         self._cam = highgui.cvCreateCameraCapture(-1)
52                 elif win32vidcap != None:
53                         try:
54                                 self._cam = win32vidcap.new_Dev(0, False)
55                         except:
56                                 pass
57
58                 self._doTimelapse = False
59                 self._bitmap = None
60
61         def hasCamera(self):
62                 return self._cam != None
63
64         def propertyPages(self):
65                 if self._cam == None:
66                         return []
67                 if cv != None:
68                         #TODO Make an OpenCV property page
69                         return []
70                 elif win32vidcap != None:
71                         return ['Image properties', 'Format properties']
72
73         def openPropertyPage(self, pageType=0):
74                 if self._cam == None:
75                         return
76                 if cv != None:
77                         pass
78                 elif win32vidcap != None:
79                         if pageType == 0:
80                                 self._cam.displaycapturefilterproperties()
81                         else:
82                                 del self._cam
83                                 self._cam = None
84                                 tmp = win32vidcap.new_Dev(0, False)
85                                 tmp.displaycapturepinproperties()
86                                 self._cam = tmp
87
88         def takeNewImage(self):
89                 if self._cam == None:
90                         return
91                 if cv != None:
92                         frame = cv.QueryFrame(self._cam)
93                         cv.CvtColor(frame, frame, cv.CV_BGR2RGB)
94                         bitmap = wx.BitmapFromBuffer(frame.width, frame.height, frame.imageData)
95                 elif win32vidcap != None:
96                         buffer, width, height = self._cam.getbuffer()
97                         try:
98                                 wxImage = wx.EmptyImage(width, height)
99                                 wxImage.SetData(buffer[::-1])
100                                 if self._bitmap != None:
101                                         del self._bitmap
102                                 bitmap = wxImage.ConvertToBitmap()
103                                 del wxImage
104                                 del buffer
105                         except:
106                                 pass
107
108                 dc = wx.MemoryDC()
109                 dc.SelectObject(bitmap)
110                 dc.DrawBitmap(self._overlayImage, bitmap.GetWidth() - self._overlayImage.GetWidth() - 5, 5, True)
111                 if profile.getPreference('machine_type') == 'ultimaker':
112                         dc.DrawBitmap(self._overlayUltimaker, (bitmap.GetWidth() - self._overlayUltimaker.GetWidth()) / 2,
113                                 bitmap.GetHeight() - self._overlayUltimaker.GetHeight() - 5, True)
114                 dc.SelectObject(wx.NullBitmap)
115
116                 self._bitmap = bitmap
117
118                 if self._doTimelapse:
119                         filename = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../__tmp_snap",
120                                 "__tmp_snap_%04d.jpg" % (self._snapshotCount)))
121                         self._snapshotCount += 1
122                         bitmap.SaveFile(filename, wx.BITMAP_TYPE_JPEG)
123
124                 return self._bitmap
125
126         def getLastImage(self):
127                 return self._bitmap
128
129         def startTimelapse(self, filename):
130                 if self._cam == None:
131                         return
132                 self._cleanTempDir()
133                 self._timelapseFilename = filename
134                 self._snapshotCount = 0
135                 self._doTimelapse = True
136                 print "startTimelapse"
137
138         def endTimelapse(self):
139                 if self._doTimelapse:
140                         ffmpeg = getFFMPEGpath()
141                         basePath = os.path.normpath(
142                                 os.path.join(os.path.split(__file__)[0], "../__tmp_snap", "__tmp_snap_%04d.jpg"))
143                         subprocess.call(
144                                 [ffmpeg, '-r', '12.5', '-i', basePath, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', '25', '-y',
145                                  '-b:v', '1500k', '-f', 'vob', self._timelapseFilename])
146                 self._doTimelapse = False
147
148         def _cleanTempDir(self):
149                 basePath = os.path.normpath(os.path.join(os.path.split(__file__)[0], "../__tmp_snap"))
150                 try:
151                         os.makedirs(basePath)
152                 except:
153                         pass
154                 for filename in glob.iglob(basePath + "/*.jpg"):
155                         os.remove(filename)