// exporter des images lisibles par les consoles cliniques
// et pas seulement importables dans e-film.
-
#ifdef __GNUC__
#include <stdint.h>
#define guint16 uint16_t
#define GDCM_EXPORT
#endif
-
//
// ---------------------------------------------------- gdcmDictEntry
//
guint16 GetElement(void){return element;};
string GetVR(void) {return vr; };
void SetVR(string);
+ void SetKey(string k){ key = k; }
bool IsVrUnknown(void);
string GetFourth(void) {return fourth;};
string GetName(void) {return name; };
typedef map<TagKey, gdcmDictEntry*> TagHT;
// Table de Hachage : (group,Elem) --> pointeur vers une ligne du Dictionnaire Dicom
-typedef map<TagKey, gdcmDictEntry*> TagHT;
-
class GDCM_EXPORT gdcmDict {
string name;
string filename;
// rempli le Dictionnaire Dicom à partir d'un fichier texte
gdcmDict(const char* FileName); // Read Dict from disk
- // QUESTION :
- // Ca doit ajouter une nouvelle entrée 'a la fin', ou 'a sa place' ?
- //
- // TODO Swig int AppendEntry(gdcmDictEntry* NewEntry);
+ int AddNewEntry (gdcmDictEntry* NewEntry);
+ int ReplaceEntry(gdcmDictEntry* NewEntry);
+ int RemoveEntry (TagKey k);
+ int RemoveEntry (guint16 group, guint16 element);
+
// renvoie une ligne de Dictionnaire Dicom à partir de (numGroup, numElement)
gdcmDictEntry * GetTag(guint32 group, guint32 element);
public:
string value; // used to be char * valeurElem
size_t Offset; // Offset from the begining of file for direct user access
+
ElValue(gdcmDictEntry*);
void SetDictEntry(gdcmDictEntry *NewEntry) { entry = NewEntry; };
-
bool IsVrUnknown(void) { return entry->IsVrUnknown(); };
-
- void SetLength(guint32 l){ LgrElem = l; };
- void SetValue(string val){ value = val; };
- void SetOffset(size_t of){ Offset = of; };
void SetImplicitVr(void) { ImplicitVr = true; };
bool IsImplicitVr(void) { return ImplicitVr; };
- void SetVR(string);
- string GetVR(void);
- string GetValue(void) { return value; };
- guint32 GetLength(void) { return LgrElem; };
- size_t GetOffset(void) { return Offset; };
- guint16 GetGroup(void) { return entry->GetGroup(); };
+
+ guint16 GetGroup(void) { return entry->GetGroup(); };
guint16 GetElement(void) { return entry->GetElement(); };
string GetKey(void) { return entry->GetKey(); };
string GetName(void) { return entry->GetName(); };
+
+ string GetVR(void) { return entry->GetVR(); };
+
+ void SetVR(string v) { entry->SetVR(v); };
+
+ // Question :
+ // Un champ privé, accessible en consultation et en modif (sans restriction)
+ // interet par rapport à un champ public ?
+ // --> pouvoir en changer la définition sans toucher à l'API
+
+ void SetLength(guint32 l){ LgrElem = l; };
+ guint32 GetLength(void) { return LgrElem; };
+
+ void SetValue(string val){ value = val; };
+ string GetValue(void) { return value; };
+
+ void SetOffset(size_t of){ Offset = of; };
+ size_t GetOffset(void) { return Offset; };
+
};
ElValue* GetElementByName (string);
string GetElValueByNumber(guint32 group, guint32 element);
string GetElValueByName (string);
- TagElValueHT & GetTagHt(void);
+
+ TagElValueHT & GetTagHt(void);
int SetElValueByNumber(string content, guint32 group, guint32 element);
int SetElValueByName(string content, string TagName);
// (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader)
-typedef string VRKey; // Ne devrait-elle pas etre utilisee dans la definition de VRHT ?
+typedef string VRKey;
typedef string VRAtr;
-typedef map<TagKey, VRAtr> VRHT; // Value Representation Hash Table
- // Cette Table de Hachage ne devrait servir qu'a determiner
- // si deux caractères correspondent à une VR existante ?
+typedef map<VRKey, VRAtr> VRHT; // Value Representation Hash Table
+
class GDCM_EXPORT gdcmHeader {
void SkipBytes(guint32);
private:
static VRHT *dicom_vr;
// Dictionaries of data elements:
-
- // Question :
- // Pourquoi mettre un pointeur statique vers le container des dictionnaires
- // (qui est une H-table de pointeurs vers des dictionnaires)
- // en plus des pointeurs vers chacun des dictionnaires ?
- // Ces derniers n'auraient-ils pas suffit ?
- //
+
static gdcmDictSet* Dicts; // global dictionary container
gdcmDict* RefPubDict; // public dictionary
gdcmDict* RefShaDict; // shadow dictionary (optional)
int PutImageDataHere(void* destination, size_t MaxSize );
+ // Question :
+ //
+ // GetImageData et PutImageDataHere
+ // Get et Put pour 2 fonctions qui font presque la meme chose :-(
+ //
+
// Allocates ExpectedSize bytes of memory at this->Data and copies the
// pointed data to it.
"multiple entries for this key (FIXME) !");
return entries.find(key)->second;
}
+
+
+int gdcmDict::ReplaceEntry(gdcmDictEntry* NewEntry) {
+
+ // au cas ou la NewEntry serait incomplete
+ // Question : cela peut-il se produire ?
+ //
+ TagKey key;
+ key = NewEntry->GetKey();
+ if (key =="") {
+ NewEntry->gdcmDictEntry::SetKey(
+ gdcmDictEntry::TranslateToKey(NewEntry->GetGroup(), NewEntry->GetElement())
+ );
+ }
+
+ entries.erase (NewEntry->gdcmDictEntry::GetKey());
+ entries[ NewEntry->GetKey()] = NewEntry;
+ return (1);
+ // Question : Dans quel cas ça peut planter ?
+}
+
+
+int gdcmDict::AddNewEntry(gdcmDictEntry* NewEntry) {
+
+ // au cas ou la NewEntry serait incomplete
+ // Question : cela peut-il se produire ?
+ //
+
+ TagKey key;
+ key = NewEntry->GetKey();
+ if (key =="") {
+ NewEntry->SetKey(
+ gdcmDictEntry::TranslateToKey(NewEntry->GetGroup(), NewEntry->GetElement())
+ );
+ }
+
+ if(entries.count(key) >= 1) {
+ printf("gdcmDict::AddNewEntry %s deja present\n", key.c_str());
+ return(0);
+ } else {
+ entries[NewEntry->GetKey()] = NewEntry;
+ return(1);
+ }
+ }
+
+
+int gdcmDict::RemoveEntry(TagKey key) {
+ if(entries.count(key) == 1) {
+ entries.erase(key);
+ return (1);
+ } else {
+ printf("gdcmDict::RemoveEntry %s non trouve\n", key.c_str());
+ return (0);
+ }
+}
+
+
+int gdcmDict::RemoveEntry (guint16 group, guint16 element) {
+
+ return( RemoveEntry(gdcmDictEntry::TranslateToKey(group, element)) );
+}
+
gdcmDictEntry::gdcmDictEntry(guint16 InGroup, guint16 InElement,
string InVr, string InFourth, string InName)
{
- group = InGroup;
- element = InElement;
- vr = InVr;
- fourth = InFourth;
- name = InName;
- key = TranslateToKey(group, element);
+ group = InGroup;
+ element = InElement;
+ vr = InVr;
+ fourth = InFourth;
+ name = InName;
+ key = TranslateToKey(group, element);
}
TagKey gdcmDictEntry::TranslateToKey(guint16 group, guint16 element) {
os << "[" << tag->second->GetVR() << "]" << endl;
}
}
-
+
int ElValSet::Write(FILE * _fp) {
+// ATTENTION : fonction non terminée (commitée a titre de precaution)
+
guint16 gr, el;
guint32 lgr;
const char * val;
- // restent à tester les echecs en écriture
+
+ // A FAIRE :
+ // parcourir la table pour recalculer la longueur des 'elements 0x0000'
+ // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
+ // dans l'image native
+ //
+ // cf : code IdDcmWriteFile
+
+/*
+ for (TagElValueHT::iterator tag = tagHt.begin();
+ tag != tagHt.end();
+ ++tag){
+
+
+ }
+*/
+ // resteront à tester les echecs en écriture
for (TagElValueHT::iterator tag = tagHt.begin();
tag != tagHt.end();
++tag){
// peut-on se passer des affectations?
// - passer l'adresse du resultat d'une fonction (???)
// - acceder au champ sans passer par un accesseur ?
- gr = tag->second->GetGroup();
- el = tag->second->GetElement();
+ gr = tag->second->GetGroup();
+ el = tag->second->GetElement();
lgr = tag->second->GetLength();
val = tag->second->GetValue().c_str();
fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element
- //fwrite ( tag->second->GetVR(),(size_t)2 ,(size_t)1 ,_fp); //VR
+ //fwrite ( tag->second->GetVR(),(size_t)2 ,(size_t)1 ,_fp); //VR
// voir pb lgr + VR
- fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr
+
+ fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr
+
+ // ATTENTION
// voir pb des int16 et int32 : les identifier, les convertir, modifier la longueur
+ // ou alors stocker la valeur 16 ou 32 bits, + un indicateur : char, int16, int32
+
fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
}
return(1);
}
+
+
+
void ElValSet::PrintByName(ostream & os) {
for (TagElValueNameHT::iterator tag = NameHt.begin();
tag != NameHt.end();
++tag){
os << tag->first << ": ";
os << "[" << tag->second->GetValue() << "]";
- os << "[" << tag->second->GetKey() << "]";
+ os << "[" << tag->second->GetKey() << "]";
os << "[" << tag->second->GetVR() << "]" << endl;
}
}
#include "gdcm.h"
-void ElValue::SetVR(string ValRep) { entry->SetVR(ValRep); }
-string ElValue::GetVR(void) { return entry->GetVR(); }
+ // void ElValue::SetVR(string v) { entry->SetVR(v); };
ElValue::ElValue(gdcmDictEntry* in) {
ImplicitVr = false;
entry = in;
}
+
+
* @return
*/
-gdcmFile::gdcmFile(string & filename)
- :gdcmHeader(filename.c_str())
+gdcmFile::gdcmFile(string & filename)
+ :gdcmHeader(filename.c_str())
{
- if (DEBUG) printf("On a echappe a gdcmHeader !\n");
}
// Nombre de Colonnes
nbCol =atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0011).c_str());
-printf("nbCol %d\n",nbCol);
-printf("nbLig %d\n",nbLignes);
-
-
// Nombre de Frames
str_nbFrames=gdcmHeader::GetPubElValByNumber(0x0028,0x0008);
} else {
nbFrames = atoi(str_nbFrames.c_str() );
}
-printf("nbFrames %d\n",nbFrames);
// Nombre de Bits Alloues pour le stockage d'un Pixel
str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
nb = atoi(str_nb.c_str() );
}
-printf("nb %d\n",nb);
-
size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
return (lgrTotale);
void * gdcmFile::GetImageData (void) {
char* _Pixels;
- int nbLignes, nbCol;
- int nbFrames, nb, nbu, highBit, signe;
+ int 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 == "gdcm::Unfound" ) {
- nbFrames = 1;
- } else {
- nbFrames = atoi(str_nbFrames.c_str() );
- }
-
- // Nombre de Bits Alloues
- str_nb=GetPubElValByNumber(0x0028,0x0100);
+ // Nombre de Bits Alloues pour le stockage d'un Pixel
+ str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
if (str_nb == "gdcm::Unfound" ) {
nb = 16;
} else {
nb = atoi(str_nb.c_str() );
}
-
+
// Nombre de Bits Utilises
str_nbu=GetPubElValByNumber(0x0028,0x0101);
}
// Longueur en Octets des Pixels a lire
- size_t _lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
+ size_t _lgrTotale = GetImageDataSize();
//Pixels = (char *) g_malloc(_lgrTotale);
_Pixels = (char *) malloc(_lgrTotale);
*/
int gdcmFile::PutImageDataHere (void* destination, size_t MaxSize) {
+
+// Question :
+// dans quel cas la Maxize sert-elle a quelque chose?
+// que fait-on si la taille de l'image est + gde que Maxize?
+// que fait-on si la taille de l'image est + petite que Maxize?
+
void * Pixels = destination; // pour garder le code identique avec GetImageData
- int nbLignes, nbCol;
- int nbFrames, nb, nbu, highBit, signe;
+ int 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 == "gdcm::Unfound" ) {
- nbFrames = 1;
- } else {
- nbFrames = atoi(str_nbFrames.c_str() );
- }
+ // Longueur en Octets des Pixels a lire
+ size_t _lgrTotale = GetImageDataSize(); // ne faudrait-il pas la stocker?
+
+ // si lgrTotale < MaxSize ==> Gros pb . A VOIR
+
+ lgrTotale = MaxSize; // pour garder le code identique avec GetImageData
+ //Pixels = (char *) malloc(lgrTotale); // pour garder le code identique avec GetImageData
- // Nombre de Bits Alloues
- str_nb=GetPubElValByNumber(0x0028,0x0100);
+ GetPixels(lgrTotale, Pixels);
+
+
+ // Nombre de Bits Alloues pour le stockage d'un Pixel
+ str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
if (str_nb == "gdcm::Unfound" ) {
nb = 16;
} else {
signe = atoi(str_signe.c_str() );
}
-
- // Longueur en Octets des Pixels a lire
- size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8);
-
- // si lgrTotale < MaxSize ==> Gros pb . A VOIR
-
- lgrTotale = MaxSize; // pour garder le code identique avec GetImageData
- //Pixels = (char *) malloc(lgrTotale); // pour garder le code identique avec GetImageData
-
- GetPixels(lgrTotale, Pixels);
+
// On remet les Octets dans le bon ordre si besoin est
if (nb != 8) {
deb ++;
}
}
-
- printf ("on est sorti\n");
-
+
// VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader
//return (Pixels); // pour garder le code identique avec GetImageData
return;
}
-
-
-
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \ingroup gdcmFile
* \brief Ecrit sur disque UNE image Dicom
* \Aucun test n'est fait sur l'"Endiannerie" du processeur.
- * \Ca sera à l'utilisateur d'appeler son Reader correctement
- * \ Equivalent a IdDcmWrite)
+ * \Ca sera à l'utilisateur d'appeler son Reader correctement.
+ * \ (Equivalent a IdDcmWrite)
*
* @param
*
}
// Ecriture Dicom File Preamble
- //filePreamble=(char*)g_malloc0(128); // voir pourquoi ca ne passe pas a la compile
filePreamble=(char*)calloc(128,1);
fwrite(filePreamble,128,1,fp1);
fwrite("DICM",4,1,fp1);
if(DEBUG) printf("Ecriture File Preamble\n");
// un accesseur de + est obligatoire ???
+
GetPubElVals().Write(fp1);
fclose (fp1);