From: frog Date: Wed, 21 May 2003 08:21:16 +0000 (+0000) Subject: * Added python wrappers of vtkGdcmReader vtk class (see the X-Git-Tag: Version0.3~47 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=00bc08e9b8fd5aadac41221a071783ef3d485f94;p=gdcm.git * Added python wrappers of vtkGdcmReader vtk class (see the source in vtk/vtkGdcmReader.cxx) : - vtk/Makefile.am now builds a library - gdcmPython/Makefile.am now builds vtkgdcmPython a second import python library (as opposed to _gdcm.so wich are the python wrappers of gdcm). vtkgdcmPython.so uses the vtk python wrappers (vtkWrapPython and vtkWrapPythonInit utility) to build vtkgdcmPython import library. - configure.in has an additional flag --enable-vtk that needs to be set to enable compilation of vtk related code, that is: + vtk/vtkGdcmReader.so and + vtk/testvtkGdcmReader C++ demo of vtk wrappers of gdcm) + gdcmPython/vtkgdcmPython.so (see above) - gdcmPython/demo/vtkGdcmDemo.py corrected (some images cannot be read when compressed or when HighBit + 1 != BitsStored), - gdcmPython/demo/vtkGdcmReader.py added. This demo illustrates the usage of the python wrapper of vtkGdcmReader vtk class. * vtk/vtkGdcmReader.cxx: bug fixed (thanks to Benoit Regrain). --- diff --git a/ChangeLog b/ChangeLog index 31c758d9..1093ecc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2003-05-21 Eric Boix with JPR + * Added python wrappers of vtkGdcmReader vtk class (see the + source in vtk/vtkGdcmReader.cxx) : + - vtk/Makefile.am now builds a library + - gdcmPython/Makefile.am now builds vtkgdcmPython a second import + python library (as opposed to _gdcm.so wich are the python + wrappers of gdcm). vtkgdcmPython.so uses the vtk python wrappers + (vtkWrapPython and vtkWrapPythonInit utility) to build vtkgdcmPython + import library. + - configure.in has an additional flag --enable-vtk that needs + to be set to enable compilation of vtk related code, that is: + + vtk/vtkGdcmReader.so and + + vtk/testvtkGdcmReader C++ demo of vtk wrappers of gdcm) + + gdcmPython/vtkgdcmPython.so (see above) + - gdcmPython/demo/vtkGdcmDemo.py corrected (some images cannot + be read when compressed or when HighBit + 1 != BitsStored), + - gdcmPython/demo/vtkGdcmReader.py added. This demo illustrates + the usage of the python wrapper of vtkGdcmReader vtk class. + * vtk/vtkGdcmReader.cxx: bug fixed (thanks to Benoit Regrain). + 2003-05-12 Eric Boix with JPR * src/gdcmHeader>[h/cxx] added gdcmHeader::GetPixelSize() * vtk/vtkGdcmReader.cxx now properly inports the image in the diff --git a/configure.in b/configure.in index cac0e468..a9845e09 100644 --- a/configure.in +++ b/configure.in @@ -37,8 +37,10 @@ AM_CONDITIONAL(HAVE_DOXYGEN, $DOXYGEN) AC_SUBST(HAVE_DOXYGEN) dnl Let people disable the doxygen stuff. -AC_ARG_ENABLE(docygen, [ --enable-doxygen Use doxygen to build documentation (default=auto)], enable_doxygen="$enableval", -enable_doxygen=auto) +AC_ARG_ENABLE(docygen, + [ --enable-doxygen Use doxygen to build documentation (default=auto)], + [enable_doxygen="$enableval"], + [enable_doxygen=auto]) if test x$enable_doxygen = xauto ; then if test x$DOXYGEN = xtrue ; then @@ -54,8 +56,9 @@ AM_CONDITIONAL(ENABLE_DOXYGEN, test x$enable_doxygen = xyes) dnl Checks for Python AC_ARG_ENABLE(python, - [ --enable-python Enable Python language support (default=no).],, - [enable_python="no"]) + [ --enable-python Enable Python language support (default=no).], + , + [enable_python="no"]) dnl AC_MSG_RESULT($enable_python) build_python=no if test "yes" = "$enable_python"; then @@ -70,8 +73,9 @@ AM_CONDITIONAL(BUILD_PYTHON, test x$build_python = xyes) dnl Checks for vtk AC_ARG_ENABLE(vtk, - [ --enable-vtk Enable vtk extensions support (default=no).],, - [enable_vtk="no"]) + [ --enable-vtk Enable vtk extensions support (default=no).], + , + [enable_vtk="no"]) AM_CONDITIONAL(BUILD_VTK, test x$enable_vtk = xyes) dnl produce Makefile.in files diff --git a/gdcmPython/Makefile.am b/gdcmPython/Makefile.am index 1440e66d..326c9ef8 100644 --- a/gdcmPython/Makefile.am +++ b/gdcmPython/Makefile.am @@ -1,27 +1,74 @@ ## Process this file with automake to produce Makefile.in -## $(top_builddir) is required for idtypes.h -GDCM_INC = -I$(top_srcdir)/src -I$(top_builddir) -SWIG_INC = $(GLIB_CFLAGS) $(PYTHON_INCLUDES) $(GDCM_INC) -INCLUDES = $(GDCM_INC) $(PYTHON_INCLUDES) +### VTK related +VTK_INC = -I/usr/include/vtk +LIBS_VTK=-L/usr/lib/vtk \ + -lvtkCommon -lvtkIO -lvtkFiltering -lvtkRendering -lvtkGraphics \ + -lvtkImaging -lvtkpng -lvtkzlib -lvtkjpeg -lvtkexpat -lvtktiff \ + -lvtkftgl -lvtkfreetype +LIBS_VTK_PYTHON= $(LIBS_VTK) \ + -lvtkCommonPython -lvtkIOPython -lvtkFilteringPython \ + -lvtkRenderingPython -lvtkGraphicsPython -lvtkImagingPython +### Gdcm itself: +GDCM_INC = -I$(top_srcdir)/src -I$(top_builddir) +### Vtk wrappers of gdcm relate: +VTKGDCM_DIR = $(top_srcdir)/vtk/ +VTKGDCM_INC = -I$(VTKGDCM_DIR) +### Swig related (for wrapping Gdcm): +SWIG_INC = $(PYTHON_INCLUDES) $(GDCM_INC) -LIBADDS = $(top_builddir)/src/libgdcm.la -lstdc++ - -### Non default rules +### The resulting include path: +INCLUDES = $(GDCM_INC) $(PYTHON_INCLUDES) $(VTK_INC) $(VTKGDCM_INC) +### Since maude_LDFLAGS cannot be defined conditionaly: pygdcm_la_LDFLAGS = -module -avoid-version -L$(top_builddir)/src/.libs +vtkgdcmPython_la_LDFLAGS = -module -avoid-version +############################################################ if BUILD_PYTHON pythondir = $(prefix)/lib/python${PYTHON_VERSION}/site-packages/gdcm -python_LTLIBRARIES = pygdcm.la +if BUILD_VTK +GDCMVTKLIB = vtkgdcmPython.la +endif +python_LTLIBRARIES = pygdcm.la $(GDCMVTKLIB) + +############ Gdcm python wrappers: pygdcm_la_SOURCES = gdcm_wrap.cxx -pygdcm_la_LIBADD = $(LIBADDS) +pygdcm_la_LIBADD = $(top_builddir)/src/libgdcm.la -lstdc++ gdcm_wrap.cxx: $(srcdir)/gdcm.i $(SWIG) -python -c++ $(SWIG_INC) -o $@ $< -MOSTLYCLEANFILES = $(pygdcm_la_SOURCES) -BUILT_SOURCES = gdcm_wrap.cxx -CLEANFILES = gdcm_wrap.cxx +############ Vtk wrappers of Gdcm wrapped for python +if BUILD_VTK +PYTHON_LIB_BASENAME=vtkgdcmPython + +# Python wrappers +PYTHON_WRAPPER = vtkWrapPython +PYTHON_WRAPPER_INIT=./vtkWrapPythonInit +PWFLAGS=hints + +vtkgdcmPython_la_SOURCES = \ + vtkGdcmReaderPython.cxx \ + vtkGdcmInit.cxx +vtkgdcmPython_la_LIBADD = $(top_builddir)/vtk/libvtkgdcm.la \ + $(LIBS_VTK_PYTHON) + +vtkGdcmReaderPython.cxx: $(VTKGDCM_DIR)/vtkGdcmReader.h + $(PYTHON_WRAPPER) $< $(PWFLAGS) $@ + +vtkGdcmInit.cxx : $(VTKGDCM_DIR)/vtkGdcmReader.h $(PYTHON_WRAPPER_INIT) + $(PYTHON_WRAPPER_INIT) $(PYTHON_LIB_BASENAME) \ + vtkGdcmReader.h \ + > $@ + +$(PYTHON_WRAPPER_INIT) : vtkWrapPythonInit.c + gcc -o $@ $< +endif### BUILD_PYTHON ####################################### + +############ Automake general usage classics: +MOSTLYCLEANFILES = $(pygdcm_la_SOURCES) $(vtkgdcmPython_la_SOURCES) +BUILT_SOURCES = $(pygdcm_la_SOURCES) $(vtkgdcmPython_la_SOURCES) +CLEANFILES = gdcm_wrap.cxx gdcm.py gdcm.pyc vtkWrapPythonInit dist-hook: rm -f $(distdir)/gdcm_wrap.cxx diff --git a/gdcmPython/demo/vtkGdcmDemo.py b/gdcmPython/demo/vtkGdcmDemo.py index 142066a1..f1e1c26f 100644 --- a/gdcmPython/demo/vtkGdcmDemo.py +++ b/gdcmPython/demo/vtkGdcmDemo.py @@ -1,4 +1,11 @@ -## A small demo that displays with VTK an image parsed with gdcm. +## A small demo that displays with VTK a dicom image parsed with gdcm. +## Warning: the parsing of header of the dicom file is done with gdcm +## but the process of in-memory loading of the image is performed +## by vtkImageReader (classical vtk operator). Since vtkImageReader +## has no special knowledge of Dicom file format, this demo +## will only work for a restrained sub-set of Dicom files (basically +## non compressed and with "HighBit + 1 != BitsStored"). +## When those conditions are not met try using vtkgdcmReader.py... import sys import vtk from gdcmPython import gdcmHeader @@ -174,8 +181,8 @@ if not check.IsReadable(): sys.exit() check = check.GetPubElVal() try: - BitsAlloc = check["Bits Allocated"] - if len(BitsAlloc) == 0 or BitsAlloc == "gdcm::Unfound": + HighBit = check["High Bit"] + if len(HighBit) == 0 or HighBit == "gdcm::Unfound": raise KeyError except KeyError: print "Gdcm couldn't find the Bits Allocated Dicom tag in file ", FileName @@ -187,9 +194,12 @@ try: except KeyError: print "Gdcm couldn't find the Bits Stored Dicom tag in file ", FileName sys.exit() -if BitsAlloc != BitsStored: +if int(HighBit) + 1 != int(BitsStored): print "vtkImageReader cannot read the file ", FileName - print " because the Bits Allocated and the Bits stored don't match." + print " because the High Bit is offseted from the BitsStored." + print " You should consider using vtkGdcmReader as opposed to the" + print " vtkImageReader python class present in this demo. Please" + print " see gdcmPython/demo/vtkGdcmReader.py for a demo." sys.exit() ### Display in a vtk RenderWindow diff --git a/gdcmPython/demo/vtkGdcmReader.py b/gdcmPython/demo/vtkGdcmReader.py new file mode 100644 index 00000000..e93b1927 --- /dev/null +++ b/gdcmPython/demo/vtkGdcmReader.py @@ -0,0 +1,65 @@ +## This demo illustrates the usage of the python-wrappers of vtkGdcmReader +## native C++ vtk class. vtkGdcmReader.cxx is a C++ level wrapper of +## gdcm which offers a vtk class vtkGdcmReader (inheriting from vtkImageReader, +## see gdcm/vtk/vtkGdcmReader.cxx). vtkgdcmPython wraps this class for +## python (by using vtk wrappers). +from vtk import * +from gdcmPython import * +from gdcmPython.vtkgdcmPython import * +import sys + +### Get filename from command line or default it +try: + FileName = sys.argv[1] +except IndexError: + FileName = os.path.join(GDCM_DATA_PATH, "test.acr") + +### Build the header element list +test = gdcmHeader(FileName) +if not test.IsReadable(): + print "The ", FileName, " file is not readable with gdcm. Sorry." + sys.exit() +del test +toDisplay = vtkGdcmReader() +toDisplay.SetFileName(FileName) +toDisplay.UpdateWholeExtent() + +VTKtable = vtkLookupTable() +VTKtable.SetNumberOfColors(1000) +VTKtable.SetTableRange(0,1000) +VTKtable.SetSaturationRange(0,0) +VTKtable.SetHueRange(0,1) +VTKtable.SetValueRange(0,1) +VTKtable.SetAlphaRange(1,1) +VTKtable.Build() + +VTKtexture = vtkTexture() +VTKtexture.SetInput(toDisplay.GetOutput()) +VTKtexture.InterpolateOn() +VTKtexture.SetLookupTable(VTKtable) + +VTKplane = vtkPlaneSource() +VTKplane.SetOrigin( -0.5, -0.5, 0.0) +VTKplane.SetPoint1( 0.5, -0.5, 0.0) +VTKplane.SetPoint2( -0.5, 0.5, 0.0) + +VTKplaneMapper = vtkPolyDataMapper() +VTKplaneMapper.SetInput(VTKplane.GetOutput()) + +VTKplaneActor = vtkActor() +VTKplaneActor.SetTexture(VTKtexture) +VTKplaneActor.SetMapper(VTKplaneMapper) +VTKplaneActor.PickableOn() + +ren = vtkRenderer() +renwin = vtkRenderWindow() +renwin.AddRenderer(ren) +iren = vtkRenderWindowInteractor() +iren.SetRenderWindow(renwin) +ren.AddActor(VTKplaneActor) +ren.SetBackground(0,0,0.5) +renwin.Render() +iren.Start() + + + diff --git a/gdcmPython/vtkWrapPythonInit.c b/gdcmPython/vtkWrapPythonInit.c new file mode 100644 index 00000000..bbc2dd26 --- /dev/null +++ b/gdcmPython/vtkWrapPythonInit.c @@ -0,0 +1,89 @@ +#include +#include +#include +char *names[1000]; +char *kitName; +int anindex = 0; + +/* warning this code is also in getclasses.cxx under pcmaker */ +void stuffit() +{ + int i; + + for (i = 0; i < anindex; i++) + { + fprintf(stdout,"extern \"C\" { PyObject *PyVTKClass_%sNew(char *); }\n", + names[i]); + } + + fprintf(stdout,"\nstatic PyMethodDef Py%s_ClassMethods[] = {\n", + kitName); + fprintf(stdout,"{NULL, NULL}};\n\n"); + + fprintf(stdout,"extern \"C\" { void init%s();}\n\n",kitName); + + /* module init function */ + fprintf(stdout,"void init%s()\n{\n",kitName); + fprintf(stdout," PyObject *m, *d, *c;\n\n"); + fprintf(stdout," static char modulename[] = \"%s\";\n",kitName); + fprintf(stdout," m = Py_InitModule(modulename, Py%s_ClassMethods);\n", + kitName); + + fprintf(stdout," d = PyModule_GetDict(m);\n"); + fprintf(stdout," if (!d) Py_FatalError(\"can't get dictionary for module %s!\");\n\n", + kitName); + + for (i = 0; i < anindex; i++) + { + fprintf(stdout," if ((c = PyVTKClass_%sNew(modulename)))\n",names[i]); + fprintf(stdout," if (-1 == PyDict_SetItemString(d, \"%s\", c))\n", + names[i]); + fprintf(stdout," Py_FatalError(\"can't add class %s to dictionary!\");\n\n", + names[i]); + } + fprintf(stdout,"}\n\n"); +} + +int main(int argc,char *argv[]) +{ + int i,j; + char tmp[128]; + FILE *file; + + if (argc < 3) + { + fprintf(stderr,"Usage: %s kit_name file1 file2 file3 ...\n",argv[0]); + exit(1); + } + + kitName = strdup(argv[1]); + + /* fill in the correct arrays */ + for (i = 2, j = 0; i < argc; i++) + { + strcpy(tmp,argv[i]); + strcpy(tmp+strlen(tmp)-2,"Python.cxx"); + file = fopen(tmp,"r"); + if (file) + { + fgets(tmp,22,file); + fclose(file); + } + if (strcmp(tmp,"// python wrapper for") != 0) + { + continue; + } + /* remove the .h and store */ + names[j] = strdup(argv[i]); + names[j++][strlen(argv[i])-2] = '\0'; + } + anindex = j; + + fprintf(stdout,"#include \n"); + fprintf(stdout,"#include \"Python.h\"\n\n"); + + stuffit(); + + return 0; +} + diff --git a/vtk/.cvsignore b/vtk/.cvsignore index e8b184e8..d7020d1a 100644 --- a/vtk/.cvsignore +++ b/vtk/.cvsignore @@ -3,3 +3,5 @@ Makefile.in Makefile vtkgdcmdemo +*.la +*.lo diff --git a/vtk/Makefile.am b/vtk/Makefile.am index 38c18fc8..9cbbc975 100644 --- a/vtk/Makefile.am +++ b/vtk/Makefile.am @@ -3,15 +3,18 @@ LIBS_VTK=-L/usr/lib/vtk \ -lvtkCommon -lvtkIO -lvtkFiltering -lvtkRendering -lvtkGraphics \ -lvtkImaging -lvtkpng -lvtkzlib -lvtkjpeg -lvtkexpat -lvtktiff \ -lvtkftgl -lvtkfreetype +LIBS_VTK_PYTHON= $(LIBS_VTK) \ + -lvtkCommonPython -lvtkIOPython -lvtkFilteringPython \ + -lvtkRenderingPython -lvtkGraphicsPython -lvtkImagingPython INCLUDE_VTK=-I/usr/include/vtk LIBS_X11= -L/usr/X11R6/lib -lX11 -lXt -lSM -lICE -lXext -lGL -## $(x_ldflags) -## $(x_libs) +#LIBS_X11= $(x_ldflags) $(x_libs) -INCLUDES = \ - -I. \ +INCLUDES = \ + -I. \ -I$(top_srcdir)/src \ + $(PYTHON_INCLUDES) \ $(INCLUDE_VTK) LDADD = \ @@ -22,9 +25,11 @@ LDADD = \ if BUILD_VTK noinst_PROGRAMS = vtkgdcmdemo vtkgdcmdemo_SOURCES = testvtkGdcmReader.cxx vtkGdcmReader.cxx +vtkgdcmdemo_LDADD = $(LDADD) +lib_LTLIBRARIES = libvtkgdcm.la +libvtkgdcm_la_SOURCES = vtkGdcmReader.cxx +libvtkgdcm_la_LIBADD = $(LDADD) else all: endif - - diff --git a/vtk/testvtkGdcmReader.cxx b/vtk/testvtkGdcmReader.cxx index 6fc520b1..c561790e 100644 --- a/vtk/testvtkGdcmReader.cxx +++ b/vtk/testvtkGdcmReader.cxx @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/vtk/Attic/testvtkGdcmReader.cxx,v 1.2 2003/05/12 14:32:43 frog Exp $ +// $Header: /cvs/public/gdcm/vtk/Attic/testvtkGdcmReader.cxx,v 1.3 2003/05/21 08:21:17 frog Exp $ #include "vtkRenderer.h" #include "vtkRenderWindow.h" @@ -49,7 +49,8 @@ int main( int argc, char *argv[] ) vtkImageData *ima = reader->GetOutput(); taille=ima->GetDimensions(); x = taille[0]; y = taille[1]; - cout << "Taille de l'image en X=" << x << " et en Y=" << y << endl; + cout << "Dimensions of the picture as read with gdcm: " + << x << " x " << y << endl; vtkLookupTable *VTKtable = vtkLookupTable::New(); VTKtable->SetNumberOfColors(1000); diff --git a/vtk/vtkGdcmReader.cxx b/vtk/vtkGdcmReader.cxx index 6f438ec7..03368d41 100644 --- a/vtk/vtkGdcmReader.cxx +++ b/vtk/vtkGdcmReader.cxx @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.2 2003/05/12 14:32:43 frog Exp $ +// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.3 2003/05/21 08:21:17 frog Exp $ #include "vtkGdcmReader.h" #include "vtkByteSwap.h" #include @@ -190,7 +190,9 @@ void vtkGdcmReader::ExecuteData(vtkDataObject *output) Source += LineSize; Destination -= LineSize; } - + // The "size" of the vtkScalars data is expressed in number of points, + // and is not the memory size representing those points: + size = size / GdcmFile.GetPixelSize(); data->GetPointData()->GetScalars()->SetVoidArray(mem, size, 0); this->Modified();