-
-// Load LUTs into memory, (as they were stored on disk)
- unsigned char *lutR = (unsigned char *)
- GetPubEntryVoidAreaByNumber(0x0028,0x1201);
- unsigned char *lutG = (unsigned char *)
- GetPubEntryVoidAreaByNumber(0x0028,0x1202);
- unsigned char *lutB = (unsigned char *)
- GetPubEntryVoidAreaByNumber(0x0028,0x1203);
-
- if (!lutR || !lutG || !lutB ) {
- return NULL;
- }
- // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
-
- unsigned char *LUTRGBA = (unsigned char *)calloc(1024,1); // 256 * 4 (R, G, B, Alpha)
- if (!LUTRGBA) {
- return NULL;
- }
- memset(LUTRGBA, 0, 1024);
- // Bits Allocated
- int nb;
- std::string str_nb = GetEntryByNumber(0x0028,0x0100);
- if (str_nb == GDCM_UNFOUND ) {
- nb = 16;
- } else {
- nb = atoi(str_nb.c_str() );
- }
- int mult;
-
- if (nbitsR==16 && nb==8) // when LUT item size is different than pixel size
- mult=2; // high byte must be = low byte
- else // See PS 3.3-2003 C.11.1.1.2 p 619
- mult=1;
-
- // if we get a black image, let's just remove the '+1'
- // from 'i*mult+1' and check again
- // if it works, we shall have to check the 3 Palettes
- // to see which byte is ==0 (first one, or second one)
- // and fix the code
- // We give up the checking to avoid some overhead
- unsigned char *a;
- int i;
-
- a = LUTRGBA+0;
- for(i=0;i<lengthR;i++) {
- *a = lutR[i*mult+1];
- a+=4;
- }
- a = LUTRGBA+1;
- for(i=0;i<lengthG;i++) {
- *a = lutG[i*mult+1];
- a+=4;
- }
- a = LUTRGBA+2;
- for(i=0;i<lengthB;i++) {
- *a = lutB[i*mult+1];
- a+=4;
- }
- a = LUTRGBA+3;
- for(i=0;i<256;i++) {
- *a = 1; // Alpha component
- a+=4;
- }
-
-//How to free the now useless LUTs?
-
-//free(LutR); free(LutB); free(LutG);
- return(LUTRGBA);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief gets the info from 0002,0010 : Transfert Syntax
- * \ else 1.
- * @return Transfert Syntax Name (as oposite to Transfert Syntax UID)
- */
-std::string gdcmHeader::GetTransfertSyntaxName(void) {
- // use the gdcmTS (TS : Transfert Syntax)
- std::string TransfertSyntax = GetEntryByNumber(0x0002,0x0010);
- if (TransfertSyntax == GDCM_UNFOUND) {
- dbg.Verbose(0, "gdcmHeader::GetTransfertSyntaxName: unfound Transfert Syntax (0002,0010)");
- return "Uncompressed ACR-NEMA";
- }
- // we do it only when we need it
- gdcmTS * ts = gdcmGlobal::GetTS();
- std::string tsName=ts->GetValue(TransfertSyntax);
- //delete ts; // Seg Fault when deleted ?!
- return tsName;
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within the public dictionary for element value of
- * a given tag.
- * @param tagName name of the searched element.
- * @return Corresponding element value when it exists, and the string
- * GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetPubEntryByName(std::string tagName) {
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
- if( dictEntry == NULL)
- return GDCM_UNFOUND;
-
- return(GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()));
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within the elements parsed with the public dictionary for
- * the element value representation of a given tag.
- *
- * Obtaining the VR (Value Representation) might be needed by caller
- * to convert the string typed content to caller's native type
- * (think of C++ vs Python). The VR is actually of a higher level
- * of semantics than just the native C++ type.
- * @param tagName name of the searched element.
- * @return Corresponding element value representation when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetPubEntryVRByName(std::string tagName) {
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
- if( dictEntry == NULL)
- return GDCM_UNFOUND;
-
- gdcmHeaderEntry* elem = GetHeaderEntryByNumber(dictEntry->GetGroup(),
- dictEntry->GetElement());
- return elem->GetVR();
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within the public dictionary for element value of
- * a given tag.
- * @param group Group of the researched tag.
- * @param element Element of the researched tag.
- * @return Corresponding element value when it exists, and the string
- * GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetPubEntryByNumber(guint16 group, guint16 element) {
- return PubEntrySet.GetEntryByNumber(group, element);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within the public dictionary for element value
- * representation of a given tag.
- *
- * Obtaining the VR (Value Representation) might be needed by caller
- * to convert the string typed content to caller's native type
- * (think of C++ vs Python). The VR is actually of a higher level
- * of semantics than just the native C++ type.
- * @param group Group of the researched tag.
- * @param element Element of the researched tag.
- * @return Corresponding element value representation when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetPubEntryVRByNumber(guint16 group, guint16 element) {
- gdcmHeaderEntry* elem = GetHeaderEntryByNumber(group, element);
- if ( !elem )
- return GDCM_UNFOUND;
- return elem->GetVR();
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Accesses an existing gdcmHeaderEntry in the PubHeaderEntrySet of this instance
- * through tag name and modifies it's content with the given value.
- * @param content new value to substitute with
- * @param tagName name of the tag to be modified
- */
-bool gdcmHeader::SetPubEntryByName(std::string content, std::string tagName) {
- //return ( PubHeaderEntrySet.SetHeaderEntryByName (content, tagName) );
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
- if( dictEntry == NULL)
- return false;
- return(PubEntrySet.SetEntryByNumber(content,
- dictEntry->GetGroup(),
- dictEntry->GetElement()));
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Accesses an existing gdcmHeaderEntry (i.e. a Dicom Element)
- * in the PubHeaderEntrySet of this instance
- * through it's (group, element) and modifies it's content with
- * the given value.
- * @param content new value to substitute with
- * @param group group of the Dicom Element to modify
- * @param element element of the Dicom Element to modify
- */
-bool gdcmHeader::SetPubEntryByNumber(std::string content, guint16 group,
- guint16 element)
-
-//TODO : homogeneiser les noms : SetPubElValByNumber
-// qui appelle PubHeaderEntrySet.SetHeaderEntryByNumber
-// pourquoi pas SetPubHeaderEntryByNumber ??
-{
- return ( PubEntrySet.SetEntryByNumber (content, group, element) );
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Accesses an existing gdcmHeaderEntry in the PubHeaderEntrySet of this instance
- * through it's (group, element) and modifies it's length with
- * the given value.
- * \warning Use with extreme caution.
- * @param length new length to substitute with
- * @param group group of the ElVal to modify
- * @param element element of the ElVal to modify
- * @return 1 on success, 0 otherwise.
- */
-
-bool gdcmHeader::SetPubEntryLengthByNumber(guint32 length, guint16 group,
- guint16 element) {
- return ( PubEntrySet.SetEntryLengthByNumber (length, group, element) );
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within elements parsed with the public dictionary
- * and then within the elements parsed with the shadow dictionary
- * for the element value of a given tag.
- * @param tagName name of the searched element.
- * @return Corresponding element value when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetEntryByName(std::string tagName) {
- return GetPubEntryByName(tagName);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within elements parsed with the public dictionary
- * and then within the elements parsed with the shadow dictionary
- * for the element value representation of a given tag.
- *
- * Obtaining the VR (Value Representation) might be needed by caller
- * to convert the string typed content to caller's native type
- * (think of C++ vs Python). The VR is actually of a higher level
- * of semantics than just the native C++ type.
- * @param tagName name of the searched element.
- * @return Corresponding element value representation when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetEntryVRByName(std::string tagName) {
- return GetPubEntryVRByName(tagName);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within elements parsed with the public dictionary
- * and then within the elements parsed with the shadow dictionary
- * for the element value of a given tag.
- * @param group Group of the searched tag.
- * @param element Element of the searched tag.
- * @return Corresponding element value representation when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetEntryByNumber(guint16 group, guint16 element) {
- return GetPubEntryByNumber(group, element);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Searches within elements parsed with the public dictionary
- * and then within the elements parsed with the shadow dictionary
- * for the element value representation of a given tag.
- *
- * Obtaining the VR (Value Representation) might be needed by caller
- * to convert the string typed content to caller's native type
- * (think of C++ vs Python). The VR is actually of a higher level
- * of semantics than just the native C++ type.
- * @param group Group of the searched tag.
- * @param element Element of the searched tag.
- * @return Corresponding element value representation when it exists,
- * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
- */
-std::string gdcmHeader::GetEntryVRByNumber(guint16 group, guint16 element) {
- return GetPubEntryVRByNumber(group, element);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Sets the value (string) of the target Dicom Element
- * @param content string value of the Dicom Element
- * @param tagName name of the searched Dicom Element.
- * @return true when found
- */
-bool gdcmHeader::SetEntryByName(std::string content,std::string tagName) {
- gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName);
- if( dictEntry == NULL)
- return false;
-
-
- TagKey key = gdcmDictEntry::TranslateToKey(dictEntry->GetGroup(),
- dictEntry->GetElement());
- if ( PubEntrySet.GetTagHT().count(key) == 0 )
- return false;
- int l = content.length();
- if(l%2) { // Odd length are padded with a space (020H).
- l++;
- content = content + '\0';
- }
-
- //tagHt[key]->SetValue(content);
- gdcmHeaderEntry * a;
- IterHT p;
- TagHeaderEntryHT::iterator p2;
- // DO NOT remove the following lines : they explain the stuff
- //p= tagHt.equal_range(key); // get a pair of iterators first-last synonym
- //p2=p.first; // iterator on the first synonym
- //a=p2->second; // H Table target column (2-nd col)
-
- // or, easier :
- a = ((PubEntrySet.GetTagHT().equal_range(key)).first)->second;
-
- a-> SetValue(content);
-
- //std::string vr = tagHt[key]->GetVR();
- std::string vr = a->GetVR();
-
- guint32 lgr;
- if( (vr == "US") || (vr == "SS") )
- lgr = 2;
- else if( (vr == "UL") || (vr == "SL") )
- lgr = 4;
- else
- lgr = l;
- //tagHt[key]->SetLength(lgr);
- a->SetLength(lgr);
- return true;
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief
- * @param exception_on_error
- * @return
- */
-FILE *gdcmHeader::OpenFile(bool exception_on_error)
- throw(gdcmFileError) {
- fp=fopen(filename.c_str(),"rb");
- if(exception_on_error) {
- if(!fp)
- throw gdcmFileError("gdcmHeader::gdcmHeader(const char *, bool)");
- }
-
- if ( fp ) {
- guint16 zero;
- fread(&zero, (size_t)2, (size_t)1, fp);
-
- //ACR -- or DICOM with no Preamble
- if( zero == 0x0008 || zero == 0x0800 || zero == 0x0002 || zero == 0x0200)
- return(fp);
-
- //DICOM
- fseek(fp, 126L, SEEK_CUR);
- char dicm[4];
- fread(dicm, (size_t)4, (size_t)1, fp);
- if( memcmp(dicm, "DICM", 4) == 0 )
- return(fp);
-
- fclose(fp);
- dbg.Verbose(0, "gdcmHeader::gdcmHeader not DICOM/ACR", filename.c_str());
- }
- else {
- dbg.Verbose(0, "gdcmHeader::gdcmHeader cannot open file", filename.c_str());
- }
- return(NULL);
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief
- * @return TRUE if the close was successfull
- */
-bool gdcmHeader::CloseFile(void) {
- int closed = fclose(fp);
- fp = (FILE *)0;
- if (! closed)
- return false;
- return true;
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief Parses the header of the file but WITHOUT loading element values.
- */
-void gdcmHeader::ParseHeader(bool exception_on_error) throw(gdcmFormatError) {
- gdcmHeaderEntry * newHeaderEntry = (gdcmHeaderEntry *)0;
-
- rewind(fp);
- CheckSwap();
- while ( (newHeaderEntry = ReadNextHeaderEntry()) ) {
- SkipHeaderEntry(newHeaderEntry);
- PubEntrySet.Add(newHeaderEntry);
- }
-}
-
-/**
- * \ingroup gdcmHeader
- * \brief
- * @return integer, acts as a Boolean
- */
-bool gdcmHeader::Write(FILE * fp, FileType type) {
-
- // TODO : move the following lines (and a lot of others, to be written)
- // to a future function CheckAndCorrectHeader
-
- if (type == ImplicitVR) {
- std::string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
- ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010);
-
- //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
- // values with a VR of UI shall be padded with a single trailing null
- // Dans le cas suivant on doit pader manuellement avec un 0
-
- PubEntrySet.SetEntryLengthByNumber(18, 0x0002, 0x0010);
- }