Commit 7137baa63a517a83e188f29eae9fa58f6b9f1ea7
1 parent
dc0b4234
Exists in
master
and in
68 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 | 55 | |
| 56 | 56 | |
| 57 | 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 | 63 | # Colour representing each orientation |
| 63 | 64 | ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red |
| ... | ... | @@ -355,7 +356,7 @@ FILETYPE_JPG = wx.NewId() |
| 355 | 356 | FILETYPE_PNG = wx.NewId() |
| 356 | 357 | FILETYPE_PS = wx.NewId() |
| 357 | 358 | FILETYPE_POV = wx.NewId() |
| 358 | -FILETYPE_OBJ = wx.NewId() | |
| 359 | +FILETYPE_TIF = wx.NewId() | |
| 359 | 360 | |
| 360 | 361 | IMAGE_TILING = {"1 x 1":(1,1), "1 x 2":(1,2), |
| 361 | 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 | 829 | 'Show text actors on viewers') |
| 830 | 830 | ps.Publisher().subscribe(self.OnHideText, |
| 831 | 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 | 890 | def OnShowText(self, pubsub_evt): |
| 834 | 891 | print "OnShowText" | ... | ... |
invesalius/data/viewer_volume.py
| ... | ... | @@ -127,8 +127,53 @@ class Viewer(wx.Panel): |
| 127 | 127 | ps.Publisher().subscribe(self.OnShowText, |
| 128 | 128 | 'Show text actors on viewers') |
| 129 | 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 | 177 | def OnCloseProject(self, pubsub_evt): |
| 133 | 178 | if self.raycasting_volume: |
| 134 | 179 | self.raycasting_volume = False | ... | ... |
invesalius/gui/dialogs.py
| ... | ... | @@ -25,8 +25,8 @@ from wx.lib.wordwrap import wordwrap |
| 25 | 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 | 30 | import session as ses |
| 31 | 31 | |
| 32 | 32 | |
| ... | ... | @@ -126,9 +126,6 @@ class ProgressDialog(object): |
| 126 | 126 | |
| 127 | 127 | |
| 128 | 128 | |
| 129 | - | |
| 130 | - | |
| 131 | - | |
| 132 | 129 | #--------- |
| 133 | 130 | WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\ |
| 134 | 131 | "All files (*.*)|*.*" |
| ... | ... | @@ -476,5 +473,54 @@ class NewSurfaceDialog(wx.Dialog): |
| 476 | 473 | #def GetValue(self): |
| 477 | 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 | 26 | import wx.lib.pubsub as ps |
| 27 | 27 | |
| 28 | 28 | import constants as const |
| 29 | +import gui.dialogs as dlg | |
| 29 | 30 | import project as proj |
| 30 | 31 | |
| 31 | 32 | BTN_MASK = wx.NewId() |
| ... | ... | @@ -180,6 +181,8 @@ class InnerTaskPanel(wx.Panel): |
| 180 | 181 | button_picture = pbtn.PlateButton(self, BTN_PICTURE, "", |
| 181 | 182 | BMP_TAKE_PICTURE, |
| 182 | 183 | style=button_style) |
| 184 | + self.button_picture = button_picture | |
| 185 | + | |
| 183 | 186 | button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", |
| 184 | 187 | BMP_EXPORT_SURFACE, |
| 185 | 188 | style=button_style) |
| ... | ... | @@ -220,9 +223,39 @@ class InnerTaskPanel(wx.Panel): |
| 220 | 223 | self.SetSizer(main_sizer) |
| 221 | 224 | self.Fit() |
| 222 | 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 | 256 | def OnLinkExportPicture(self, evt=None): |
| 225 | - pass | |
| 257 | + self.button_picture.PopupMenu(self.menu_picture) | |
| 258 | + | |
| 226 | 259 | |
| 227 | 260 | def OnLinkExportMask(self, evt=None): |
| 228 | 261 | project = proj.Project() | ... | ... |