URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-25 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Fix DICOM implementation: was DCMTK, now is GDCM.
* mln/io/dicom/load.hh: GDCM version.
---
load.hh | 338 ++++++++++++----------------------------------------------------
1 file changed, 65 insertions(+), 273 deletions(-)
Index: trunk/milena/mln/io/dicom/load.hh
===================================================================
--- trunk/milena/mln/io/dicom/load.hh (revision 3422)
+++ trunk/milena/mln/io/dicom/load.hh (revision 3423)
@@ -25,72 +25,27 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*
- *
- * Copyright (C) 1994-2005, OFFIS
- *
- * This software and supporting documentation were developed by
- *
- * Kuratorium OFFIS e.V.
- * Healthcare Information and Communication Systems
- * Escherweg 2
- * D-26121 Oldenburg, Germany
- *
- * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
- * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
- * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
- * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
- * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
- *
- * Module: dcmdata
- *
- * Author: Gerd Ehlers
- *
- * Purpose: List the contents of a dicom file
- *
- * Last Update: $Author: meichel $
- * Update Date: $Date: 2005/12/08 15:40:46 $
- * CVS/RCS Revision: $Revision: 1.55 $
- * Status: $State: Exp $
- *
- * CVS/RCS Log at end of file
- *
- */
-
#ifndef MLN_IO_DICOM_LOAD_HH
# define MLN_IO_DICOM_LOAD_HH
/*!
- * \file mln/io/dicom/load.hh
+ * \file mln/io/magick/load.hh
*
- * \brief Define a function which loads an image of kind dicom with
+ * \brief Define a function which loads an image of kind magick with
* given path.
*
*/
-# include <mln/io/pnm/load.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image3d.hh>
-# include <dcmtk/config/osconfig.h> /* make sure OS specific configuration is
included first */
-# include <dcmtk/ofstd/ofstream.h>
-# include <dcmtk/dcmdata/dctk.h>
-# include <dcmtk/dcmdata/dcdebug.h>
-# include <dcmtk/dcmdata/cmdlnarg.h>
-# include <dcmtk/ofstd/ofconapp.h>
-# include <dcmtk/dcmdata/dcuid.h> /* for dcmtk version name */
-# include <dcmtk/dcmdata/dcistrmz.h> /* for dcmZlibExpectRFC1950Encoding */
-
-# define INCLUDE_CSTDLIB
-# define INCLUDE_CSTRING
-# include <dcmtk/ofstd/ofstdinc.h>
-
-# ifdef WITH_ZLIB
-# include <zlib.h> /* for zlibVersion() */
-# endif
-
-# define SHORTCOL 3
-# define LONGCOL 20
-# define PATH_SEPARATOR '/'
+# include <mln/algebra/vec.hh>
+# include <gdcmReader.h>
+# include <gdcmImageReader.h>
+# include <gdcmWriter.h>
+# include <gdcmDataSet.h>
+# include <gdcmAttribute.h>
namespace mln
@@ -112,37 +67,15 @@
void load(Image<I>& ima,
const std::string& filename);
- /*! Load a dicom image in a Milena image. To use this routine, you
- * should specialize the template whith the value type of the
- * image loaded. (ex : load<value::int_u8>("...") )
- *
- * \param[in] filename The image source.
- *
- * \return An image2d which contains loaded data.
- */
- template <typename V>
- image2d<V> load(const std::string& filename);
-
- /*! Load a dicom image in a Milena image. To use this routine, you
- * should specialize the template whith the value type of the
- * image loaded. (ex : load<value::int_u8>("...") )
- *
- * \param[in] filename The image source.
- *
- * \return An image2d which contains loaded data.
- */
- template <typename V>
- image3d<V> load(const std::string& filename);
-
# ifndef MLN_INCLUDE_ONLY
template <typename V>
inline
image2d<V> load(const std::string& filename)
{
- trace::entering("mln::io::dicom::load");
- image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
- trace::exiting("mln::io::dicom::load");
+ trace::entering("mln::io::gdcm::load");
+ image2d<V> ima;// = io::pnm::load<V>(MAGICK, filename);
+ trace::exiting("mln::io::gdcm::load");
return ima;
}
@@ -150,228 +83,87 @@
inline
image3d<V> load(const std::string& filename)
{
- trace::entering("mln::io::dicom::load");
- image2d<V> ima;// = io::pnm::load<V>(DICOM, filename);
- trace::exiting("mln::io::dicom::load");
+ trace::entering("mln::io::gdcm::load");
+ image2d<V> ima;// = io::pnm::load<V>(MAGICK, filename);
+ trace::exiting("mln::io::gdcm::load");
return ima;
}
-
-
-
-
- static OFBool printAllInstances = OFTrue;
- static OFBool prependSequenceHierarchy = OFFalse;
- static int printTagCount = 0;
- static const int MAX_PRINT_TAG_NAMES = 1024;
- static const char* printTagNames[MAX_PRINT_TAG_NAMES];
- static const DcmTagKey* printTagKeys[MAX_PRINT_TAG_NAMES];
- static OFCmdUnsignedInt maxReadLength = 4096; // default is 4 KB
-
- static OFBool addPrintTagName(const char* tagName)
- {
- if (printTagCount >= MAX_PRINT_TAG_NAMES) {
- std::cerr << "error: too many print Tag options (max: " <<
MAX_PRINT_TAG_NAMES << ")" << endl;
- return OFFalse;
- }
-
- unsigned int group = 0xffff;
- unsigned int elem = 0xffff;
- if (sscanf(tagName, "%x,%x", &group, &elem) != 2)
- {
- /* it is a name */
- const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
- const DcmDictEntry *dicent = globalDataDict.findEntry(tagName);
- if (dicent == NULL)
- {
- std::cerr << "error: unrecognised tag name: '" << tagName
<< "'" << endl;
- dcmDataDict.unlock();
- return OFFalse;
- }
- else
- {
- /* note for later */
- printTagKeys[printTagCount] = new DcmTagKey(dicent->getKey());
- }
- dcmDataDict.unlock();
- }
- else
- {
- /* tag name has format xxxx,xxxx */
- /* do not lookup in dictionary, tag could be private */
- printTagKeys[printTagCount] = NULL;
- }
-
- printTagNames[printTagCount] = strcpy(OFstatic_cast(char*, malloc(strlen(tagName)+1)),
tagName);
- printTagCount++;
- return OFTrue;
- }
-
-
template <typename I>
- static void printResult(Image<I>& ima, DcmStack& stack, size_t
printFlags)
+ inline
+ void load(Image<I>& ima_,
+ const std::string& filename)
{
- unsigned long n = stack.card();
- if (n == 0)
- return;
-
- if (prependSequenceHierarchy) {
- /* print the path leading up to the top stack elem */
- for (unsigned long i = n - 1; i >= 1; i--) {
- DcmObject *dobj = stack.elem(i);
- /* do not print if a DCM_Item as this is not
- * very helpful to distinguish instances.
- */
- if (dobj != NULL && dobj->getTag().getXTag() != DCM_Item) {
- char buf[512];
- sprintf(buf, "(%x,%x).",
- OFstatic_cast(unsigned, dobj->getGTag()),
- OFstatic_cast(unsigned, dobj->getETag()));
- std::cout << buf;
- }
- }
- }
+ trace::entering("mln::io::gdcm::load");
- /* print the tag and its value */
- DcmObject *dobj = stack.top();
- dobj->print(std::cout, printFlags);
- }
+ using value::int_u16;
+ I& ima = exact(ima_);
- template <typename I>
- static int dumpFile(Image<I>& ima,
- const char *ifname,
- const E_FileReadMode readMode,
- const E_TransferSyntax xfer,
- const size_t printFlags,
- const OFBool loadIntoMemory,
- const OFBool stopOnErrors,
- const OFBool writePixelData,
- const char *pixelDirectory)
+ gdcm::ImageReader r;
+ r.SetFileName(filename.c_str());
+ if (!r.Read())
{
- int result = 0;
+ std::cerr << "error: cannot open file '" << filename
<< "'!";
+ abort();
+ }
- DcmFileFormat dfile;
- DcmObject *dset = &dfile;
+ gdcm::File &file = r.GetFile();
+ gdcm::DataSet& ds = file.GetDataSet();
- if (readMode == ERM_dataset)
- dset = dfile.getDataset();
+ gdcm::Image& image = r.GetImage();
- // Load file
+ char* dataBuffer = new char[image.GetBufferLength()];
+ image.GetBuffer(dataBuffer);
- OFCondition cond = dfile.loadFile(ifname, xfer, EGL_noChange, maxReadLength, readMode);
+ int ndims = image.GetNumberOfDimensions();
+ const unsigned int* dims = image.GetDimensions();
- // Read error
+ unsigned short bytes_allocated = image.GetPixelFormat().GetBitsAllocated() / 8;
+ unsigned short samples_per_pixel = image.GetPixelFormat().GetSamplesPerPixel();
- if (!cond.good())
+ if (mln_site_(I)::dim != ndims)
{
- std::cerr << "error: " << dfile.error().text()
- << ": reading file: "<< ifname << endl;
- result = 1;
- if (stopOnErrors)
- return result;
+ std::cerr << "error: dimension mismatch" << std::endl;
+ abort();
}
- if (loadIntoMemory)
- dfile.loadAllDataIntoMemory();
-
- if (printTagCount == 0)
- {
- if (writePixelData)
- {
- OFString str = ifname;
- OFString rname = pixelDirectory;
- if ((rname.length() > 0) && (rname[rname.length() - 1] !=
PATH_SEPARATOR))
- rname += PATH_SEPARATOR;
- size_t pos = str.find_last_of(PATH_SEPARATOR);
- if (pos == OFString_npos)
- rname += str;
- else
- rname += str.substr(pos + 1);
- size_t counter = 0;
- dset->print(std::cout, printFlags, 0 /*level*/, rname.c_str(), &counter);
- }
- else
- dset->print(std::cout, printFlags);
- }
- else
- {
- /* only print specified tags */
- for (int i = 0; i < printTagCount; i++)
+ algebra::vec<mln_site_(I)::dim, unsigned int> vmin;
+ algebra::vec<mln_site_(I)::dim, unsigned int> vmax;
+ algebra::vec<mln_site_(I)::dim, unsigned int> vdims;
+ for (int i = ndims - 1; i >= 0; --i)
{
- unsigned int group = 0xffff;
- unsigned int elem = 0xffff;
- DcmTagKey searchKey;
- const char* tagName = printTagNames[i];
- if (printTagKeys[i])
- searchKey = *printTagKeys[i];
+ vmin[i] = 0;
+ vmax[i] = dims[ndims - i - 1] - 1;
+ if (i == ndims - 1)
+ vdims[i] = 1;
else
- {
- if (sscanf(tagName, "%x,%x", &group, &elem) == 2)
- searchKey.set(group, elem);
- else
- {
- std::cerr << "Internal ERROR in File " << __FILE__ <<
", Line "
- << __LINE__ << std::endl
- << "-- Named tag inconsistency" << std::endl;
- abort();
- }
+ vdims[i] = dims[ndims - i - 2] * vdims[i + 1];
}
- DcmStack stack;
- if (dset->search(searchKey, stack, ESM_fromHere, OFTrue) == EC_Normal)
+ mln_site(I) pmin(vmin);
+ mln_site(I) pmax(vmax);
+ mln_concrete(I) result(box<mln_site(I)>(pmin, pmax));
+ initialize(ima, result);
+ mln_piter(I) p(ima.domain());
+ unsigned int index = 0;
+ for_all(p)
{
- printResult(ima, stack, printFlags);
- if (printAllInstances)
+ index = 0;
+ for (int i = 0; i < ndims; ++i)
{
- while (dset->search(searchKey, stack, ESM_afterStackTop, OFTrue) == EC_Normal)
- printResult(ima, stack, printFlags);
- }
+ index += p.to_site().to_vec()[i] * vdims[i];
}
- }
- }
-
- return result;
- }
-
-
- template <typename I>
- inline
- void load(Image<I>& ima,
- const std::string& filename)
+ ima(p) = dataBuffer[index * bytes_allocated * samples_per_pixel];
+ // FIXME: RGB support, HighBit
+ for (int j = 1; j < bytes_allocated; ++j)
{
- trace::entering("mln::io::dicom::load");
-
- std::ifstream file(filename.c_str());
- if (! file)
- {
- std::cerr << "error: cannot open file '" << filename
<< "'!";
- abort();
+ ima(p) *= 256;
+ ima(p) += dataBuffer[(index * bytes_allocated + j) * samples_per_pixel];
}
-
- int opt_debugMode = 0;
- OFBool loadIntoMemory = OFTrue;
- size_t printFlags = DCMTypes::PF_shortenLongTagValues /*|
DCMTypes::PF_showTreeStructure*/;
- OFBool printFilename = OFFalse;
- OFBool writePixelData = OFFalse;
- E_FileReadMode readMode = ERM_autoDetect;
- E_TransferSyntax xfer = EXS_Unknown;
- OFBool stopOnErrors = OFTrue;
- const char *current = NULL;
- const char *pixelDirectory = NULL;
-
-
- /* make sure data dictionary is loaded */
- if (!dcmDataDict.isDictionaryLoaded())
- {
- std::cerr << "Warning: no data dictionary loaded, "
- << "check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE;
}
- int errorCount = 0;
- dumpFile(ima, current, readMode, xfer, printFlags, loadIntoMemory, stopOnErrors,
- writePixelData, pixelDirectory);
+ delete(dataBuffer);
trace::exiting("mln::io::dicom::load");
}