Commit 7137baa63a517a83e188f29eae9fa58f6b9f1ea7
1 parent
dc0b4234
Exists in
master
and in
6 other branches
ADD: Photo feature (fix #59)
Showing
5 changed files
with
193 additions
and
11 deletions
Show diff stats
invesalius/constants.py
@@ -55,9 +55,10 @@ TEXT_POS_VCENTRE_LEFT = (X, 0.5) # SetVerticalJustificationToCentered | @@ -55,9 +55,10 @@ TEXT_POS_VCENTRE_LEFT = (X, 0.5) # SetVerticalJustificationToCentered | ||
55 | 55 | ||
56 | 56 | ||
57 | # Slice orientation | 57 | # Slice orientation |
58 | -AXIAL = 0 | ||
59 | -CORONAL = 1 | ||
60 | -SAGITAL = 2 | 58 | +AXIAL = 1 |
59 | +CORONAL = 2 | ||
60 | +SAGITAL = 3 | ||
61 | +VOLUME = 4 | ||
61 | 62 | ||
62 | # Colour representing each orientation | 63 | # Colour representing each orientation |
63 | ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red | 64 | ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red |
@@ -355,7 +356,7 @@ FILETYPE_JPG = wx.NewId() | @@ -355,7 +356,7 @@ FILETYPE_JPG = wx.NewId() | ||
355 | FILETYPE_PNG = wx.NewId() | 356 | FILETYPE_PNG = wx.NewId() |
356 | FILETYPE_PS = wx.NewId() | 357 | FILETYPE_PS = wx.NewId() |
357 | FILETYPE_POV = wx.NewId() | 358 | FILETYPE_POV = wx.NewId() |
358 | -FILETYPE_OBJ = wx.NewId() | 359 | +FILETYPE_TIF = wx.NewId() |
359 | 360 | ||
360 | IMAGE_TILING = {"1 x 1":(1,1), "1 x 2":(1,2), | 361 | IMAGE_TILING = {"1 x 1":(1,1), "1 x 2":(1,2), |
361 | "1 x 3":(1,3), "1 x 4":(1,4), | 362 | "1 x 3":(1,3), "1 x 4":(1,4), |
invesalius/data/viewer_slice.py
@@ -829,6 +829,63 @@ class Viewer(wx.Panel): | @@ -829,6 +829,63 @@ class Viewer(wx.Panel): | ||
829 | 'Show text actors on viewers') | 829 | 'Show text actors on viewers') |
830 | ps.Publisher().subscribe(self.OnHideText, | 830 | ps.Publisher().subscribe(self.OnHideText, |
831 | 'Hide text actors on viewers') | 831 | 'Hide text actors on viewers') |
832 | + ps.Publisher().subscribe(self.OnExportPicture,'Export picture to file') | ||
833 | + | ||
834 | + | ||
835 | + | ||
836 | + def OnExportPicture(self, pubsub_evt): | ||
837 | + ps.Publisher().sendMessage('Begin busy cursor') | ||
838 | + | ||
839 | + id, filename, filetype = pubsub_evt.data | ||
840 | + dict = {"AXIAL": const.AXIAL, | ||
841 | + "CORONAL": const.CORONAL, | ||
842 | + "SAGITAL": const.SAGITAL} | ||
843 | + | ||
844 | + if id == dict[self.orientation]: | ||
845 | + print "ok" | ||
846 | + if filetype == const.FILETYPE_POV: | ||
847 | + print 1 | ||
848 | + renwin = self.interactor.GetRenderWindow() | ||
849 | + image = vtk.vtkWindowToImageFilter() | ||
850 | + image.SetInput(renwin) | ||
851 | + writer = vtk.vtkPOVExporter() | ||
852 | + writer.SetFilePrefix(filename.split(".")[0]) | ||
853 | + writer.SetRenderWindow(renwin) | ||
854 | + writer.Write() | ||
855 | + return | ||
856 | + else: | ||
857 | + print 2 | ||
858 | + #Use tiling to generate a large rendering. | ||
859 | + image = vtk.vtkRenderLargeImage() | ||
860 | + image.SetInput(self.ren) | ||
861 | + image.SetMagnification(2) | ||
862 | + | ||
863 | + image = image.GetOutput() | ||
864 | + | ||
865 | + | ||
866 | + # write image file | ||
867 | + if (filetype == const.FILETYPE_BMP): | ||
868 | + print 3 | ||
869 | + writer = vtk.vtkBMPWriter() | ||
870 | + elif (filetype == const.FILETYPE_JPG): | ||
871 | + print 4 | ||
872 | + writer = vtk.vtkJPEGWriter() | ||
873 | + elif (filetype == const.FILETYPE_PNG): | ||
874 | + print 5 | ||
875 | + writer = vtk.vtkPNGWriter() | ||
876 | + elif (filetype == const.FILETYPE_PS): | ||
877 | + print 6 | ||
878 | + writer = vtk.vtkPostScriptWriter() | ||
879 | + elif (filetype == const.FILETYPE_TIF): | ||
880 | + print 7 | ||
881 | + writer = vtk.vtkTIFFWriter() | ||
882 | + filename = "%s.tif"%filename.strip(".tif") | ||
883 | + | ||
884 | + writer.SetInput(image) | ||
885 | + writer.SetFileName(filename) | ||
886 | + writer.Write() | ||
887 | + | ||
888 | + ps.Publisher().sendMessage('End busy cursor') | ||
832 | 889 | ||
833 | def OnShowText(self, pubsub_evt): | 890 | def OnShowText(self, pubsub_evt): |
834 | print "OnShowText" | 891 | print "OnShowText" |
invesalius/data/viewer_volume.py
@@ -127,8 +127,53 @@ class Viewer(wx.Panel): | @@ -127,8 +127,53 @@ class Viewer(wx.Panel): | ||
127 | ps.Publisher().subscribe(self.OnShowText, | 127 | ps.Publisher().subscribe(self.OnShowText, |
128 | 'Show text actors on viewers') | 128 | 'Show text actors on viewers') |
129 | ps.Publisher().subscribe(self.OnCloseProject, 'Close project data') | 129 | ps.Publisher().subscribe(self.OnCloseProject, 'Close project data') |
130 | + ps.Publisher().subscribe(self.OnExportPicture,'Export picture to file') | ||
130 | 131 | ||
131 | - | 132 | + |
133 | + | ||
134 | + def OnExportPicture(self, pubsub_evt): | ||
135 | + ps.Publisher().sendMessage('Begin busy cursor') | ||
136 | + id, filename, filetype = pubsub_evt.data | ||
137 | + | ||
138 | + if id == const.VOLUME: | ||
139 | + if filetype == const.FILETYPE_POV: | ||
140 | + renwin = self.interactor.GetRenderWindow() | ||
141 | + image = vtk.vtkWindowToImageFilter() | ||
142 | + image.SetInput(renwin) | ||
143 | + writer = vtk.vtkPOVExporter() | ||
144 | + writer.SetFilePrefix(filename.split(".")[0]) | ||
145 | + writer.SetRenderWindow(renwin) | ||
146 | + writer.Write() | ||
147 | + return | ||
148 | + else: | ||
149 | + #Use tiling to generate a large rendering. | ||
150 | + image = vtk.vtkRenderLargeImage() | ||
151 | + image.SetInput(self.ren) | ||
152 | + image.SetMagnification(2) | ||
153 | + | ||
154 | + image = image.GetOutput() | ||
155 | + | ||
156 | + | ||
157 | + # write image file | ||
158 | + if (filetype == const.FILETYPE_BMP): | ||
159 | + writer = vtk.vtkBMPWriter() | ||
160 | + elif (filetype == const.FILETYPE_JPG): | ||
161 | + writer = vtk.vtkJPEGWriter() | ||
162 | + elif (filetype == const.FILETYPE_PNG): | ||
163 | + writer = vtk.vtkPNGWriter() | ||
164 | + elif (filetype == const.FILETYPE_PS): | ||
165 | + writer = vtk.vtkPostScriptWriter() | ||
166 | + elif (filetype == const.FILETYPE_TIF): | ||
167 | + writer = vtk.vtkTIFFWriter() | ||
168 | + filename = "%s.tif"%filename.strip(".tif") | ||
169 | + | ||
170 | + writer.SetInput(image) | ||
171 | + writer.SetFileName(filename) | ||
172 | + writer.Write() | ||
173 | + ps.Publisher().sendMessage('End busy cursor') | ||
174 | + | ||
175 | + | ||
176 | + | ||
132 | def OnCloseProject(self, pubsub_evt): | 177 | def OnCloseProject(self, pubsub_evt): |
133 | if self.raycasting_volume: | 178 | if self.raycasting_volume: |
134 | self.raycasting_volume = False | 179 | self.raycasting_volume = False |
invesalius/gui/dialogs.py
@@ -25,8 +25,8 @@ from wx.lib.wordwrap import wordwrap | @@ -25,8 +25,8 @@ from wx.lib.wordwrap import wordwrap | ||
25 | import wx.lib.pubsub as ps | 25 | import wx.lib.pubsub as ps |
26 | 26 | ||
27 | 27 | ||
28 | - | ||
29 | -import project | 28 | +import constants as const |
29 | +import project as proj | ||
30 | import session as ses | 30 | import session as ses |
31 | 31 | ||
32 | 32 | ||
@@ -126,9 +126,6 @@ class ProgressDialog(object): | @@ -126,9 +126,6 @@ class ProgressDialog(object): | ||
126 | 126 | ||
127 | 127 | ||
128 | 128 | ||
129 | - | ||
130 | - | ||
131 | - | ||
132 | #--------- | 129 | #--------- |
133 | WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\ | 130 | WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\ |
134 | "All files (*.*)|*.*" | 131 | "All files (*.*)|*.*" |
@@ -476,5 +473,54 @@ class NewSurfaceDialog(wx.Dialog): | @@ -476,5 +473,54 @@ class NewSurfaceDialog(wx.Dialog): | ||
476 | #def GetValue(self): | 473 | #def GetValue(self): |
477 | # return self.text.GetValue() + _("| mask: ") + MASK_LIST[self.combo_surface_name.GetSelection()] | 474 | # return self.text.GetValue() + _("| mask: ") + MASK_LIST[self.combo_surface_name.GetSelection()] |
478 | 475 | ||
476 | +INDEX_TO_EXTENSION = {0: "bmp", 1: "jpg", 2: "png", 3: "ps", 4:"povray", 5:"tiff"} | ||
477 | +WILDCARD_SAVE_PICTURE = _("BMP image")+" (*.bmp)|*.bmp|"+\ | ||
478 | + _("JPG image")+" (*.jpg)|*.jpg|"+\ | ||
479 | + _("PNG image")+" (*.png)|*.png|"+\ | ||
480 | + _("PostScript document")+" (*.ps)|*.ps|"+\ | ||
481 | + _("POV-Ray file)")+" (*.pov)|*.pov|"+\ | ||
482 | + _("TIFF image")+" (*.tif)|*.tif" | ||
483 | + | ||
484 | + | ||
485 | +def ExportPicture(type_=""): | ||
486 | + import constants as const | ||
487 | + | ||
488 | + INDEX_TO_TYPE = {0: const.FILETYPE_BMP, | ||
489 | + 1: const.FILETYPE_JPG, | ||
490 | + 2: const.FILETYPE_PNG, | ||
491 | + 3: const.FILETYPE_PS, | ||
492 | + 4: const.FILETYPE_POV, | ||
493 | + 5: const.FILETYPE_TIF} | ||
494 | + | ||
495 | + print "ExportPicture" | ||
496 | + project = proj.Project() | ||
497 | + | ||
498 | + if sys.platform == 'win32': | ||
499 | + project_name = project.name | ||
500 | + else: | ||
501 | + project_name = project.name+".jpg" | ||
502 | + | ||
503 | + | ||
504 | + dlg = wx.FileDialog(None, | ||
505 | + "Save %s picture as..." %type_, | ||
506 | + "", # last used directory | ||
507 | + "%s_%s"%(project_name, type_), # filename | ||
508 | + WILDCARD_SAVE_PICTURE, | ||
509 | + wx.SAVE|wx.OVERWRITE_PROMPT) | ||
510 | + dlg.SetFilterIndex(1) # default is VTI | ||
511 | + | ||
512 | + if dlg.ShowModal() == wx.ID_OK: | ||
513 | + filetype_index = dlg.GetFilterIndex() | ||
514 | + filetype = INDEX_TO_TYPE[filetype_index] | ||
515 | + extension = INDEX_TO_EXTENSION[filetype_index] | ||
516 | + filename = dlg.GetPath() | ||
517 | + print "filename", filename | ||
518 | + if sys.platform != 'win32': | ||
519 | + if filename.split(".")[-1] != extension: | ||
520 | + filename = filename + "."+ extension | ||
521 | + return filename, filetype | ||
522 | + else: | ||
523 | + return () | ||
524 | + | ||
479 | 525 | ||
480 | 526 |
invesalius/gui/task_exporter.py
@@ -26,6 +26,7 @@ import wx.lib.platebtn as pbtn | @@ -26,6 +26,7 @@ import wx.lib.platebtn as pbtn | ||
26 | import wx.lib.pubsub as ps | 26 | import wx.lib.pubsub as ps |
27 | 27 | ||
28 | import constants as const | 28 | import constants as const |
29 | +import gui.dialogs as dlg | ||
29 | import project as proj | 30 | import project as proj |
30 | 31 | ||
31 | BTN_MASK = wx.NewId() | 32 | BTN_MASK = wx.NewId() |
@@ -180,6 +181,8 @@ class InnerTaskPanel(wx.Panel): | @@ -180,6 +181,8 @@ class InnerTaskPanel(wx.Panel): | ||
180 | button_picture = pbtn.PlateButton(self, BTN_PICTURE, "", | 181 | button_picture = pbtn.PlateButton(self, BTN_PICTURE, "", |
181 | BMP_TAKE_PICTURE, | 182 | BMP_TAKE_PICTURE, |
182 | style=button_style) | 183 | style=button_style) |
184 | + self.button_picture = button_picture | ||
185 | + | ||
183 | button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", | 186 | button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", |
184 | BMP_EXPORT_SURFACE, | 187 | BMP_EXPORT_SURFACE, |
185 | style=button_style) | 188 | style=button_style) |
@@ -220,9 +223,39 @@ class InnerTaskPanel(wx.Panel): | @@ -220,9 +223,39 @@ class InnerTaskPanel(wx.Panel): | ||
220 | self.SetSizer(main_sizer) | 223 | self.SetSizer(main_sizer) |
221 | self.Fit() | 224 | self.Fit() |
222 | self.sizer = main_sizer | 225 | self.sizer = main_sizer |
226 | + self.__init_menu() | ||
227 | + | ||
228 | + def __init_menu(self): | ||
229 | + | ||
230 | + | ||
231 | + menu = wx.Menu() | ||
232 | + self.id_to_name = {const.AXIAL:_("Axial slice"), | ||
233 | + const.CORONAL:_("Coronal slice"), | ||
234 | + const.SAGITAL:_("Sagittal slice"), | ||
235 | + const.VOLUME:_("Volume")} | ||
236 | + | ||
237 | + for id in self.id_to_name: | ||
238 | + item = wx.MenuItem(menu, id, self.id_to_name[id]) | ||
239 | + menu.AppendItem(item) | ||
240 | + | ||
241 | + self.menu_picture = menu | ||
242 | + menu.Bind(wx.EVT_MENU, self.OnMenuPicture) | ||
243 | + | ||
244 | + def OnMenuPicture(self, evt): | ||
245 | + print "OnMenuPicture" | ||
246 | + id = evt.GetId() | ||
247 | + value = dlg.ExportPicture(self.id_to_name[id]) | ||
248 | + if value: | ||
249 | + filename, filetype = value | ||
250 | + print filename, filetype | ||
251 | + ps.Publisher().sendMessage('Export picture to file', | ||
252 | + (id, filename, filetype)) | ||
253 | + | ||
254 | + | ||
223 | 255 | ||
224 | def OnLinkExportPicture(self, evt=None): | 256 | def OnLinkExportPicture(self, evt=None): |
225 | - pass | 257 | + self.button_picture.PopupMenu(self.menu_picture) |
258 | + | ||
226 | 259 | ||
227 | def OnLinkExportMask(self, evt=None): | 260 | def OnLinkExportMask(self, evt=None): |
228 | project = proj.Project() | 261 | project = proj.Project() |