Commit 160fcc1f698b3818c4fa794007e190783f6337a9
1 parent
718f8735
Exists in
master
and in
68 other branches
ADD: Export surface in several formats and vtkImageData
Showing
4 changed files
with
115 additions
and
17 deletions
Show diff stats
invesalius/constants.py
@@ -218,6 +218,10 @@ FILETYPE_RIB = wx.NewId() | @@ -218,6 +218,10 @@ FILETYPE_RIB = wx.NewId() | ||
218 | FILETYPE_STL = wx.NewId() | 218 | FILETYPE_STL = wx.NewId() |
219 | FILETYPE_VRML = wx.NewId() | 219 | FILETYPE_VRML = wx.NewId() |
220 | FILETYPE_OBJ = wx.NewId() | 220 | FILETYPE_OBJ = wx.NewId() |
221 | +FILETYPE_VTP = wx.NewId() | ||
222 | +FILETYPE_PLY = wx.NewId() | ||
223 | + | ||
224 | +FILETYPE_IMAGEDATA = wx.NewId() | ||
221 | 225 | ||
222 | FILETYPE_BMP = wx.NewId() | 226 | FILETYPE_BMP = wx.NewId() |
223 | FILETYPE_JPG = wx.NewId() | 227 | FILETYPE_JPG = wx.NewId() |
invesalius/data/slice_.py
@@ -4,6 +4,7 @@ import vtk | @@ -4,6 +4,7 @@ import vtk | ||
4 | import wx.lib.pubsub as ps | 4 | import wx.lib.pubsub as ps |
5 | 5 | ||
6 | import constants as const | 6 | import constants as const |
7 | +import imagedata_utils as iu | ||
7 | from mask import Mask | 8 | from mask import Mask |
8 | from project import Project | 9 | from project import Project |
9 | from utils import Singleton | 10 | from utils import Singleton |
@@ -60,6 +61,7 @@ class Slice(object): | @@ -60,6 +61,7 @@ class Slice(object): | ||
60 | 'Change colour table from background image') | 61 | 'Change colour table from background image') |
61 | 62 | ||
62 | ps.Publisher().subscribe(self.InputImageWidget, 'Input Image in the widget') | 63 | ps.Publisher().subscribe(self.InputImageWidget, 'Input Image in the widget') |
64 | + ps.Publisher().subscribe(self.OnExportMask,'Export mask to file') | ||
63 | 65 | ||
64 | def __set_current_mask_threshold_limits(self, pubsub_evt): | 66 | def __set_current_mask_threshold_limits(self, pubsub_evt): |
65 | thresh_min = pubsub_evt.data[0] | 67 | thresh_min = pubsub_evt.data[0] |
@@ -544,3 +546,15 @@ class Slice(object): | @@ -544,3 +546,15 @@ class Slice(object): | ||
544 | imagedata_mask.Update() | 546 | imagedata_mask.Update() |
545 | 547 | ||
546 | return imagedata_mask | 548 | return imagedata_mask |
549 | + | ||
550 | + | ||
551 | + def OnExportMask(self, pubsub_evt): | ||
552 | + #imagedata = self.current_mask.imagedata | ||
553 | + imagedata = self.imagedata | ||
554 | + filename, filetype = pubsub_evt.data | ||
555 | + if (filetype == const.FILETYPE_IMAGEDATA): | ||
556 | + iu.Export(imagedata, filename) | ||
557 | + | ||
558 | + | ||
559 | + | ||
560 | + |
invesalius/data/surface.py
@@ -284,7 +284,11 @@ class SurfaceManager(): | @@ -284,7 +284,11 @@ class SurfaceManager(): | ||
284 | 284 | ||
285 | def OnExportSurface(self, pubsub_evt): | 285 | def OnExportSurface(self, pubsub_evt): |
286 | filename, filetype = pubsub_evt.data | 286 | filename, filetype = pubsub_evt.data |
287 | - if filetype == const.FILETYPE_STL: | 287 | + if (filetype == const.FILETYPE_STL) or\ |
288 | + (filetype == const.FILETYPE_VTP): | ||
289 | + | ||
290 | + # First we identify all surfaces that are selected | ||
291 | + # (if any) | ||
288 | proj = prj.Project() | 292 | proj = prj.Project() |
289 | polydata_list = [] | 293 | polydata_list = [] |
290 | for index in proj.surface_dict: | 294 | for index in proj.surface_dict: |
@@ -299,10 +303,24 @@ class SurfaceManager(): | @@ -299,10 +303,24 @@ class SurfaceManager(): | ||
299 | else: | 303 | else: |
300 | polydata = pu.Merge(polydata_list) | 304 | polydata = pu.Merge(polydata_list) |
301 | 305 | ||
302 | - writer = vtk.vtkSTLWriter() | ||
303 | - writer.SetFileTypeToBinary() | 306 | + |
307 | + # Having a polydata that represents all surfaces | ||
308 | + # selected, we write it, according to filetype | ||
309 | + if filetype == const.FILETYPE_STL: | ||
310 | + writer = vtk.vtkSTLWriter() | ||
311 | + writer.SetFileTypeToBinary() | ||
312 | + elif filetype == const.FILETYPE_VTP: | ||
313 | + writer = vtk.vtkXMLPolyDataWriter() | ||
314 | + elif filetype == const.FILETYPE_IV: | ||
315 | + writer = vtk.vtkIVWriter() | ||
316 | + elif filetype == const.FILETYPE_PLY: | ||
317 | + writer = vtk.vtkPLYWriter() | ||
318 | + writer.SetFileTypeToBinary() | ||
319 | + writer.SetDataByteOrderToLittleEndian() | ||
320 | + #writer.SetColorModeToUniformCellColor() | ||
321 | + #writer.SetColor(255, 0, 0) | ||
322 | + | ||
304 | writer.SetFileName(filename) | 323 | writer.SetFileName(filename) |
305 | writer.SetInput(polydata) | 324 | writer.SetInput(polydata) |
306 | writer.Write() | 325 | writer.Write() |
307 | 326 | ||
308 | - |
invesalius/gui/task_exporter.py
@@ -28,26 +28,34 @@ import wx.lib.pubsub as ps | @@ -28,26 +28,34 @@ import wx.lib.pubsub as ps | ||
28 | import constants as const | 28 | import constants as const |
29 | import project as proj | 29 | import project as proj |
30 | 30 | ||
31 | +BTN_MASK = wx.NewId() | ||
31 | BTN_PICTURE = wx.NewId() | 32 | BTN_PICTURE = wx.NewId() |
32 | BTN_SURFACE = wx.NewId() | 33 | BTN_SURFACE = wx.NewId() |
33 | BTN_REPORT = wx.NewId() | 34 | BTN_REPORT = wx.NewId() |
34 | BTN_REQUEST_RP = wx.NewId() | 35 | BTN_REQUEST_RP = wx.NewId() |
35 | 36 | ||
36 | WILDCARD_SAVE_3D = "Inventor (*.iv)|*.iv|"\ | 37 | WILDCARD_SAVE_3D = "Inventor (*.iv)|*.iv|"\ |
38 | + "PLY (*.ply)|*.ply|"\ | ||
37 | "Renderman (*.rib)|*.rib|"\ | 39 | "Renderman (*.rib)|*.rib|"\ |
38 | "STL (*.stl)|*.stl|"\ | 40 | "STL (*.stl)|*.stl|"\ |
39 | "VRML (*.vrml)|*.vrml|"\ | 41 | "VRML (*.vrml)|*.vrml|"\ |
42 | + "VTK PolyData (*.vtp)|*.vtp|"\ | ||
40 | "Wavefront (*.obj)|*.obj" | 43 | "Wavefront (*.obj)|*.obj" |
44 | + | ||
41 | INDEX_TO_TYPE_3D = {0: const.FILETYPE_IV, | 45 | INDEX_TO_TYPE_3D = {0: const.FILETYPE_IV, |
42 | - 1: const.FILETYPE_RIB, | ||
43 | - 2: const.FILETYPE_STL, | ||
44 | - 3: const.FILETYPE_VRML, | ||
45 | - 4: const.FILETYPE_OBJ} | 46 | + 1: const.FILETYPE_PLY, |
47 | + 2: const.FILETYPE_RIB, | ||
48 | + 3: const.FILETYPE_STL, | ||
49 | + 4: const.FILETYPE_VRML, | ||
50 | + 5: const.FILETYPE_VTP, | ||
51 | + 6: const.FILETYPE_OBJ} | ||
46 | INDEX_TO_EXTENSION = {0: "iv", | 52 | INDEX_TO_EXTENSION = {0: "iv", |
47 | - 1: "rib", | ||
48 | - 2: "stl", | ||
49 | - 3: "vrml", | ||
50 | - 4: "obj"} | 53 | + 1: "ply", |
54 | + 2: "rib", | ||
55 | + 3: "stl", | ||
56 | + 4: "vrml", | ||
57 | + 5: "vtp", | ||
58 | + 6: "obj"} | ||
51 | 59 | ||
52 | WILDCARD_SAVE_2D = "BMP (*.bmp)|*.bmp|"\ | 60 | WILDCARD_SAVE_2D = "BMP (*.bmp)|*.bmp|"\ |
53 | "JPEG (*.jpg)|*.jpg|"\ | 61 | "JPEG (*.jpg)|*.jpg|"\ |
@@ -62,6 +70,8 @@ INDEX_TO_TYPE_2D = {0: const.FILETYPE_BMP, | @@ -62,6 +70,8 @@ INDEX_TO_TYPE_2D = {0: const.FILETYPE_BMP, | ||
62 | 4: const.FILETYPE_POV, | 70 | 4: const.FILETYPE_POV, |
63 | 5: const.FILETYPE_OBJ} | 71 | 5: const.FILETYPE_OBJ} |
64 | 72 | ||
73 | +WILDCARD_SAVE_MASK = "VTK ImageData (*.vti)|*.vti" | ||
74 | + | ||
65 | 75 | ||
66 | class TaskPanel(wx.Panel): | 76 | class TaskPanel(wx.Panel): |
67 | def __init__(self, parent): | 77 | def __init__(self, parent): |
@@ -109,6 +119,17 @@ class InnerTaskPanel(wx.Panel): | @@ -109,6 +119,17 @@ class InnerTaskPanel(wx.Panel): | ||
109 | link_export_surface.Bind(hl.EVT_HYPERLINK_LEFT, | 119 | link_export_surface.Bind(hl.EVT_HYPERLINK_LEFT, |
110 | self.OnLinkExportSurface) | 120 | self.OnLinkExportSurface) |
111 | 121 | ||
122 | + tooltip = wx.ToolTip("Export 3D mask (voxels)") | ||
123 | + link_export_mask = hl.HyperLinkCtrl(self, -1,"Export mask...") | ||
124 | + link_export_mask.SetUnderlines(False, False, False) | ||
125 | + link_export_mask.SetColours("BLACK", "BLACK", "BLACK") | ||
126 | + link_export_mask.SetToolTip(tooltip) | ||
127 | + link_export_mask.AutoBrowse(False) | ||
128 | + link_export_mask.UpdateLink() | ||
129 | + link_export_mask.Bind(hl.EVT_HYPERLINK_LEFT, | ||
130 | + self.OnLinkExportMask) | ||
131 | + | ||
132 | + | ||
112 | #tooltip = wx.ToolTip("Request rapid prototyping services") | 133 | #tooltip = wx.ToolTip("Request rapid prototyping services") |
113 | #link_request_rp = hl.HyperLinkCtrl(self,-1,"Request rapid prototyping...") | 134 | #link_request_rp = hl.HyperLinkCtrl(self,-1,"Request rapid prototyping...") |
114 | #link_request_rp.SetUnderlines(False, False, False) | 135 | #link_request_rp.SetUnderlines(False, False, False) |
@@ -136,14 +157,19 @@ class InnerTaskPanel(wx.Panel): | @@ -136,14 +157,19 @@ class InnerTaskPanel(wx.Panel): | ||
136 | BMP_TAKE_PICTURE = wx.Bitmap(\ | 157 | BMP_TAKE_PICTURE = wx.Bitmap(\ |
137 | "../icons/tool_photo_original.png", | 158 | "../icons/tool_photo_original.png", |
138 | wx.BITMAP_TYPE_PNG) | 159 | wx.BITMAP_TYPE_PNG) |
160 | + BMP_EXPORT_MASK = wx.Bitmap("../icons/mask.png", | ||
161 | + wx.BITMAP_TYPE_PNG) | ||
139 | else: | 162 | else: |
140 | BMP_EXPORT_SURFACE = wx.Bitmap("../icons/surface_export.png", | 163 | BMP_EXPORT_SURFACE = wx.Bitmap("../icons/surface_export.png", |
141 | wx.BITMAP_TYPE_PNG) | 164 | wx.BITMAP_TYPE_PNG) |
142 | BMP_TAKE_PICTURE = wx.Bitmap("../icons/tool_photo.png", | 165 | BMP_TAKE_PICTURE = wx.Bitmap("../icons/tool_photo.png", |
143 | wx.BITMAP_TYPE_PNG) | 166 | wx.BITMAP_TYPE_PNG) |
167 | + BMP_EXPORT_MASK = wx.Bitmap("../icons/mask_small.png", | ||
168 | + wx.BITMAP_TYPE_PNG) | ||
144 | 169 | ||
145 | 170 | ||
146 | - bmp_list = [BMP_TAKE_PICTURE, BMP_EXPORT_SURFACE] | 171 | + bmp_list = [BMP_TAKE_PICTURE, BMP_EXPORT_SURFACE, |
172 | + BMP_EXPORT_MASK] | ||
147 | for bmp in bmp_list: | 173 | for bmp in bmp_list: |
148 | bmp.SetWidth(25) | 174 | bmp.SetWidth(25) |
149 | bmp.SetHeight(25) | 175 | bmp.SetHeight(25) |
@@ -157,6 +183,9 @@ class InnerTaskPanel(wx.Panel): | @@ -157,6 +183,9 @@ class InnerTaskPanel(wx.Panel): | ||
157 | button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", | 183 | button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", |
158 | BMP_EXPORT_SURFACE, | 184 | BMP_EXPORT_SURFACE, |
159 | style=button_style) | 185 | style=button_style) |
186 | + button_mask = pbtn.PlateButton(self, BTN_MASK, "", | ||
187 | + BMP_EXPORT_MASK, | ||
188 | + style=button_style) | ||
160 | #button_request_rp = pbtn.PlateButton(self, BTN_REQUEST_RP, "", | 189 | #button_request_rp = pbtn.PlateButton(self, BTN_REQUEST_RP, "", |
161 | # BMP_IMPORT, style=button_style) | 190 | # BMP_IMPORT, style=button_style) |
162 | #button_report = pbtn.PlateButton(self, BTN_REPORT, "", | 191 | #button_report = pbtn.PlateButton(self, BTN_REPORT, "", |
@@ -170,12 +199,14 @@ class InnerTaskPanel(wx.Panel): | @@ -170,12 +199,14 @@ class InnerTaskPanel(wx.Panel): | ||
170 | flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP | 199 | flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP |
171 | flag_button = wx.EXPAND | wx.GROW | 200 | flag_button = wx.EXPAND | wx.GROW |
172 | 201 | ||
173 | - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=2, vgap=0) | 202 | + fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0) |
174 | fixed_sizer.AddGrowableCol(0, 1) | 203 | fixed_sizer.AddGrowableCol(0, 1) |
175 | fixed_sizer.AddMany([ (link_export_picture, 1, flag_link, 3), | 204 | fixed_sizer.AddMany([ (link_export_picture, 1, flag_link, 3), |
176 | (button_picture, 0, flag_button), | 205 | (button_picture, 0, flag_button), |
177 | (link_export_surface, 1, flag_link, 3), | 206 | (link_export_surface, 1, flag_link, 3), |
178 | - (button_surface, 0, flag_button)])#, | 207 | + (button_surface, 0, flag_button),#])#, |
208 | + (link_export_mask, 1, flag_link, 3), | ||
209 | + (button_mask, 0, flag_button)]) | ||
179 | #(link_report, 0, flag_link, 3), | 210 | #(link_report, 0, flag_link, 3), |
180 | #(button_report, 0, flag_button), | 211 | #(button_report, 0, flag_button), |
181 | #(link_request_rp, 1, flag_link, 3), | 212 | #(link_request_rp, 1, flag_link, 3), |
@@ -193,8 +224,37 @@ class InnerTaskPanel(wx.Panel): | @@ -193,8 +224,37 @@ class InnerTaskPanel(wx.Panel): | ||
193 | def OnLinkExportPicture(self, evt=None): | 224 | def OnLinkExportPicture(self, evt=None): |
194 | pass | 225 | pass |
195 | 226 | ||
227 | + def OnLinkExportMask(self, evt=None): | ||
228 | + project = proj.Project() | ||
229 | + print "OnLinkEportMask" | ||
230 | + if sys.platform == 'win32': | ||
231 | + project_name = project.name | ||
232 | + else: | ||
233 | + project_name = project.name+".vti" | ||
234 | + | ||
235 | + | ||
236 | + dlg = wx.FileDialog(None, | ||
237 | + "Save mask as...", # title | ||
238 | + "", # last used directory | ||
239 | + project_name, # filename | ||
240 | + WILDCARD_SAVE_MASK, | ||
241 | + wx.SAVE|wx.OVERWRITE_PROMPT) | ||
242 | + dlg.SetFilterIndex(0) # default is VTI | ||
243 | + | ||
244 | + if dlg.ShowModal() == wx.ID_OK: | ||
245 | + filename = dlg.GetPath() | ||
246 | + print "filename", filename | ||
247 | + extension = "vti" | ||
248 | + if sys.platform != 'win32': | ||
249 | + if filename.split(".")[-1] != extension: | ||
250 | + filename = filename + "."+ extension | ||
251 | + filetype = const.FILETYPE_IMAGEDATA | ||
252 | + ps.Publisher().sendMessage('Export mask to file', | ||
253 | + (filename, filetype)) | ||
254 | + | ||
196 | 255 | ||
197 | def OnLinkExportSurface(self, evt=None): | 256 | def OnLinkExportSurface(self, evt=None): |
257 | + "OnLinkExportSurface" | ||
198 | project = proj.Project() | 258 | project = proj.Project() |
199 | n_surface = 0 | 259 | n_surface = 0 |
200 | 260 | ||
@@ -215,7 +275,7 @@ class InnerTaskPanel(wx.Panel): | @@ -215,7 +275,7 @@ class InnerTaskPanel(wx.Panel): | ||
215 | project_name, # filename | 275 | project_name, # filename |
216 | WILDCARD_SAVE_3D, | 276 | WILDCARD_SAVE_3D, |
217 | wx.SAVE|wx.OVERWRITE_PROMPT) | 277 | wx.SAVE|wx.OVERWRITE_PROMPT) |
218 | - dlg.SetFilterIndex(2) # default is STL | 278 | + dlg.SetFilterIndex(3) # default is STL |
219 | 279 | ||
220 | if dlg.ShowModal() == wx.ID_OK: | 280 | if dlg.ShowModal() == wx.ID_OK: |
221 | filetype_index = dlg.GetFilterIndex() | 281 | filetype_index = dlg.GetFilterIndex() |
@@ -252,5 +312,7 @@ class InnerTaskPanel(wx.Panel): | @@ -252,5 +312,7 @@ class InnerTaskPanel(wx.Panel): | ||
252 | self.OnLinkExportSurface() | 312 | self.OnLinkExportSurface() |
253 | elif id == BTN_REPORT: | 313 | elif id == BTN_REPORT: |
254 | self.OnLinkReport() | 314 | self.OnLinkReport() |
255 | - else: #elif id == BTN_REQUEST_RP: | 315 | + elif id == BTN_REQUEST_RP: |
256 | self.OnLinkRequestRP() | 316 | self.OnLinkRequestRP() |
317 | + else:# id == BTN_MASK: | ||
318 | + self.OnLinkExportMask() |