IsExplicitBigEndianTransfertSyntax IsJPEGSpectralSelectionTransfertSyntax, etc...
(Je ne suis pas sur que ce soit la bonne maniere dee proceder.
Il y en a VINGT-CING en tout,
J'ai craque au bout de 8 ...
Y a-t-il la possibilite de faire chose generalisable ?
{
typedef map<string, char*> dict;
- dict current;
- dict::iterator im = current.find("00380010");
- current["00100010"] = "Patient Name";
- current["7fe00010"] = "Pixel Data";
- current["50000010"] = "Number of points";
- current["00380010"] = "Admission ID";
+ dict tb1;
+ dict::iterator im = tb1.find("00380010");
+ tb1["00100010"] = "Patient Name";
+ tb1["7fe00010"] = "Pixel Data";
+ tb1["50000010"] = "Number of points";
+ tb1["00380010"] = "Admission ID";
cout << "Traversal of dictionary (note the proper ordering on key)." << endl;
- for ( dict::iterator im = current.begin(); im != current.end(); ++im )
+ for ( dict::iterator im = tb1.begin(); im != tb1.end(); ++im )
cout << " \"" << im->first << "\" = " << im->second << endl;
cout << "End of dictionary." << endl;
cout << "Find request on key 00380010" << endl;
- im = current.find("00380010");
+ im = tb1.find("00380010");
cout << " \"" << im->first << "\" = " << im->second << endl;
}
#ifdef _MSC_VER
typedef unsigned short guint16;
-typedef unsigned int guint32;
+typedef unsigned int guint32;
#endif
#ifdef _MSC_VER
// + ce qu'on est allé chercher dans le Dictionnaire Dicom)
//
+// QUESTION:
+//
+// Ne faudrait-il pas trouver un autre nom, qui preterait moins à confusion?
+// ElValue n'EST PAS la 'valeur d'un Element', mais la reunion d'infos
+// trouvees dans l'Entete" du fichier ET dans le Dictionnaire
+//
// The dicom header of a Dicom file contains a set of such ELement VALUES
// (when successfuly parsed against a given Dicom dictionary)
//
////////////////////////////////////////////////////////////////////////////
-// Container for a set of succefully parsed ElValues.
+// Container for a set of successfully parsed ElValues.
typedef map<TagKey, ElValue*> TagElValueHT;
typedef map<string, ElValue*> TagElValueNameHT;
void Print(ostream &);
void PrintByName(ostream &);
ElValue* GetElementByNumber(guint32 group, guint32 element);
- ElValue* GetElementByName(string);
- string GetElValueByNumber(guint32 group, guint32 element);
- string GetElValueByName(string);
+ ElValue* GetElementByName (string);
+ string GetElValueByNumber(guint32 group, guint32 element);
+ string GetElValueByName (string);
TagElValueHT & GetTagHt(void);
};
// outside of the elements:
guint16 grPixel;
guint16 numPixel;
+ // Ne faudrait-il pas une indication sur la presence ou non
+ // du 'groupe des pixels' dans l'entete?
+ // (voir pb du DICOMDIR)
// Swap code (little, big, big-bad endian): this code is not fixed
// during parsing.FIXME sw should be an enum e.g.
void SwitchSwapToBigEndian(void);
void FixFoundLength(ElValue*, guint32);
bool IsAnInteger(ElValue *);
- bool IsBigEndianTransferSyntax(void);
+
+ bool IsImplicitVRLittleEndianTransferSyntax(void);
+ bool IsExplicitVRLittleEndianTransferSyntax(void);
+ bool IsDeflatedExplicitVRLittleEndianTransferSyntax(void);
+ bool IsExplicitVRBigEndianTransferSyntax(void);
+ bool IsJPEGBaseLineProcess1TransferSyntax(void);
+ bool IsJPEGExtendedProcess2_4TransferSyntax(void);
+ bool IsJPEGExtendedProcess3_5TransferSyntax(void);
+ bool IsJPEGSpectralSelectionProcess6_8TransferSyntax(void);
+//
+// Euhhhhhhh
+// Il y en a encore DIX-SEPT, comme ça.
+// Il faudrait trouver qq chose + rusé ...
+//
+
+
+
void SetMaxSizeLoadElementValue(long);
ElValue * ReadNextElement(void);
gdcmDictEntry * IsInDicts(guint32, guint32);
////// relationship between a gdcmFile and gdcmHeader is of
////// type IS_A or HAS_A !
-class GDCM_EXPORT gdcmFile: gdcmHeader
+class GDCM_EXPORT gdcmFile: public gdcmHeader
{
private:
void* Data;
// Allocates necessary memory, copies the data (image[s]/volume[s]) to
// newly allocated zone and return a pointer to it:
- // TODO Swig void * GetImageData();
+
+ void * GetImageData();
// Returns size (in bytes) of required memory to contain data
// represented in this file.
- // TODO Swig size_t GetImageDataSize();
+
+ size_t GetImageDataSize();
// Copies (at most MaxSize bytes) of data to caller's memory space.
// Returns an error code on failure (if MaxSize is not big enough)
#include "gdcm.h"
+static void _Swap(void* im, int swap, int lgr, int nb);
+
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ * \brief Constructor dedicated to writing a new DICOMV3 part10 compliant
+ * \file (see SetFileName, SetDcmTag and Write)
+ * \Opens (in read only and when possible) an existing file and checks
+ * \for DICOM compliance. Returns NULL on failure.
+ * \Note: the in-memory representation of all available tags found in
+ * \the DICOM header is post-poned to first header information access.
+ * \This avoid a double parsing of public part of the header when
+ * \one sets an a posteriori shadow dictionary (efficiency can be
+ * \seen as a side effect).
+ *
+ * @param
+ *
+ * @return
+ */
+
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ * \brief constructeur
+ *
+ * @param
+ *
+ * @return
+ */
+
+
gdcmFile::gdcmFile(string & filename)
:gdcmHeader(filename.c_str())
{
+}
+
+
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ * \brief Renvoie la longueur A ALLOUER pour recevoir les pixels de l'image
+ * \ ou DES images dans le cas d'un multiframe
+ * \ ATTENTION : il ne s'agit PAS de la lgr du groupe des Pixels
+ * \ (dans le cas d'images compressees, elle n'a pas de sens).
+ *
+ * @param void Rien en entree
+ *
+ * @return longueur a allouer
+ */
+
+size_t gdcmFile::GetImageDataSize(void) {
+ int nbLignes, nbCol, nbFrames, nb;
+ string str_nbFrames, str_nb;
+ // Nombre de Lignes
+ nbLignes=atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0010).c_str());
+ // Nombre de Colonnes
+ nbCol =atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0011).c_str());
+
+ // Nombre de Frames
+ str_nbFrames=gdcmHeader::GetPubElValByNumber(0x0028,0x0008);
+
+ if (str_nbFrames == "UNFOUND" ) {
+ nbFrames = 1;
+ } else {
+ nbFrames = atoi(str_nbFrames.c_str() );
+ }
+ // Nombre de Bits Alloues pour le stockage d'un Pixel
+ str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
+
+ if (str_nb == "UNFOUND" ) {
+ nb = 16;
+ } else {
+ nb = atoi(str_nb.c_str() );
+ }
+
+ size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
+ return (lgrTotale);
+
}
+
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ * \brief amene en mémoire les Pixels d'une image NON COMPRESSEE
+ * \Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image
+ *
+ * @param rien
+ *
+ * @return Pointeur sur la zone mémoire contenant les Pixels lus
+ */
+
+void * gdcmFile::GetImageData (void) {
+
+ char* Pixels;
+ int nbLignes, nbCol;
+
+ int nbFrames, nb, nbu, highBit, signe;
+ string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
+
+ unsigned short int mask = 0xffff;
+
+ // Nombre de Lignes
+ nbLignes=atoi(GetPubElValByNumber(0x0028,0x0010).c_str());
+ // Nombre de Colonnes
+ nbCol =atoi(GetPubElValByNumber(0x0028,0x0011).c_str());
+
+ // Nombre de Frames
+ str_nbFrames=GetPubElValByNumber(0x0028,0x0008);
+
+
+ if (str_nbFrames == "UNFOUND" ) {
+ nbFrames = 1;
+ } else {
+ nbFrames = atoi(str_nbFrames.c_str() );
+ }
+
+ // Nombre de Bits Alloues
+ str_nb=GetPubElValByNumber(0x0028,0x0100);
+
+ if (str_nb == "UNFOUND" ) {
+ nb = 16;
+ } else {
+ nb = atoi(str_nb.c_str() );
+ }
+
+ // Nombre de Bits Utilises
+ str_nbu=GetPubElValByNumber(0x0028,0x0101);
+
+ if (str_nbu == "UNFOUND" ) {
+ nbu = nb;
+ } else {
+ nbu = atoi(str_nbu.c_str() );
+ }
+
+ // Position du Bit de Poids Fort
+ str_highBit=GetPubElValByNumber(0x0028,0x0102);
+
+ if (str_highBit == "UNFOUND" ) {
+ highBit = nb - 1;
+ } else {
+ highBit = atoi(str_highBit.c_str() );
+ }
+
+ // Signe des Pixels
+ str_signe=GetPubElValByNumber(0x0028,0x0103);
+
+ if (str_signe == "UNFOUND" ) {
+ signe = 1;
+ } else {
+ signe = atoi(str_signe.c_str() );
+ }
+
+ // Longueur en Octets des Pixels a lire
+ size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
+
+ //Pixels = (char *) g_malloc(lgrTotale);
+ Pixels = (char *) malloc(lgrTotale);
+
+ GetPixels(lgrTotale, Pixels);
+
+ // On remet les Octets dans le bon ordre si besoin est
+ if (nb != 8) {
+ //int sw = GetSwapCode();
+
+ // _Swap (Pixels, sw, lgrTotale, nb); // A REMETTRE
+ }
+
+ // On remet les Bits des Octets dans le bon ordre si besoin est
+ //
+ // ATTENTION : Jamais confronté a des pixels stockes sur 32 bits
+ // avec moins de 32 bits utilises
+ // et dont le bit de poids fort ne serait pas la ou on l'attend ...
+ // --> ne marchera pas dans ce cas
+ if (nbu!=nb){
+ mask = mask >> (nb-nbu);
+ int l=(int)lgrTotale/(nb/8);
+ unsigned short *deb = (unsigned short *)Pixels;
+ for(int i=0;i<l;i++) {
+ *deb = (*deb >> (nbu-highBit-1)) & mask;
+ deb ++;
+ }
+ }
+
+ printf ("on est sorti\n");
+
+ // VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader
+
+ return (Pixels);
+}
+
+
+//
+// Je laisse le code integral, au cas ça puisse etre reutilise ailleurs
+//
+
+static void _Swap(void* im, int swap, int lgr, int nb) {
+guint32 s32;
+guint16 fort,faible;
+int i;
+
+if(nb == 16)
+
+ switch(swap) {
+ case 0:
+ case 12:
+ case 1234:
+ break;
+
+ case 21:
+ case 3412:
+ case 2143:
+ case 4321:
+
+ for(i=0;i<lgr;i++)
+ ((unsigned short int*)im)[i]= ((((unsigned short int*)im)[i])>>8)
+ | ((((unsigned short int*)im)[i])<<8);
+ break;
+
+ default:
+ printf("valeur de SWAP (16 bits) non autorisee : %d\n", swap);
+ }
+
+if( nb == 32 )
+
+ switch (swap) {
+ case 0:
+ case 1234:
+ break;
+
+ case 4321:
+ for(i=0;i<lgr;i++) {
+ faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 4321 */
+ fort =((unsigned long int*)im)[i]>>16;
+ fort= (fort>>8) | (fort<<8);
+ faible=(faible>>8) | (faible<<8);
+ s32=faible;
+ ((unsigned long int*)im)[i]=(s32<<16)|fort;
+ }
+ break;
+
+ case 2143:
+ for(i=0;i<lgr;i++) {
+ faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 2143 */
+ fort=((unsigned long int*)im)[i]>>16;
+ fort= (fort>>8) | (fort<<8);
+ faible=(faible>>8) | (faible<<8);
+ s32=fort;
+ ((unsigned long int*)im)[i]=(s32<<16)|faible;
+ }
+ break;
+
+ case 3412:
+ for(i=0;i<lgr;i++) {
+ faible= ((unsigned long int*)im)[i]&0x0000ffff; /* 3412 */
+ fort=((unsigned long int*)im)[i]>>16;
+ s32=faible;
+ ((unsigned long int*)im)[i]=(s32<<16)|fort;
+ }
+ break;
+
+ default:
+ printf("valeur de SWAP (32 bits) non autorisee : %d\n", swap);
+ }
+return;
+}
+
+
+
fread(Pixels, 1, lgrTotale, fp);
}
+
+
/**
* \ingroup gdcmHeader
* \brief Find the value representation of the current tag.
* effectivement lue
* @return longueur retenue pour le champ
*/
+
+// -->
+// --> Oops
+// --> C'etait la description de quoi, ca?
+// -->
void gdcmHeader::FindVR( ElValue *ElVal) {
if (filetype != ExplicitVR)
/**
* \ingroup gdcmHeader
* \brief Determines if the Transfer Syntax was allready encountered
- * and if it corresponds to a Big Endian one.
+ * and if it corresponds to a ImplicitVRLittleEndian one.
+ *
+ * @return True when ImplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsImplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a ExplicitVRLittleEndian one.
+ *
+ * @return True when ExplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsExplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.1" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a DeflatedExplicitVRLittleEndian one.
+ *
+ * @return True when DeflatedExplicitVRLittleEndian found. False in all other cases.
+ */
+bool gdcmHeader::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.1.99" )
+ return true;
+ return false;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a Explicit VR Big Endian one.
*
* @return True when big endian found. False in all other cases.
*/
-bool gdcmHeader::IsBigEndianTransferSyntax(void) {
+bool gdcmHeader::IsExplicitVRBigEndianTransferSyntax(void) {
ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
if ( !Element )
return false;
return false;
}
-void gdcmHeader::FixFoundLength(ElValue * ElVal, guint32 FoudLength) {
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGBaseLineProcess1 one.
+ *
+ * @return True when JPEGBaseLineProcess1found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.50" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGExtendedProcess2-4 one.
+ *
+ * @return True when JPEGExtendedProcess2-4 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.51" )
+ return true;
+ return false;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGExtendeProcess3-5 one.
+ *
+ * @return True when JPEGExtendedProcess3-5 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.52" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was allready encountered
+ * and if it corresponds to a JPEGSpectralSelectionProcess6-8 one.
+ *
+ * @return True when JPEGSpectralSelectionProcess6-8 found. False in all other cases.
+ */
+bool gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void) {
+ ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.4.53" )
+ return true;
+ return false;
+}
+
+//
+// Euhhhhhhh
+// Il y en a encore DIX-SEPT, comme ça.
+// Il faudrait trouver qq chose + rusé ...
+//
+
+
+void gdcmHeader::FixFoundLength(ElValue * ElVal, guint32 FoundLength) {
// Heuristic: a final fix.
- if ( FoudLength == 0xffffffff)
- FoudLength = 0;
- ElVal->SetLength(FoudLength);
+ if ( FoundLength == 0xffffffff)
+ FoundLength = 0;
+ ElVal->SetLength(FoundLength);
}
guint32 gdcmHeader::FindLengthOB(void) {
// hands on a big endian encoded file: we switch the swap code to
// big endian and proceed...
if ( (element == 0x000) && (length16 == 0x0400) ) {
- if ( ! IsBigEndianTransferSyntax() )
+ if ( ! IsExplicitVRBigEndianTransferSyntax() )
throw Error::FileReadError(fp, "gdcmHeader::FindLength");
length16 = 4;
SwitchSwapToBigEndian();
}
// FIXME The exact size should be length if we move to strings or whatever
+
+ //
+ // QUESTION : y a-t-il une raison pour ne pas utiliser g_malloc ici ?
+ //
+
char* NewValue = (char*)malloc(length+1);
if( !NewValue) {
dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue");