X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmFileHelper.cxx;h=b61faace8ed0fd7c8a1d2a4c6ba82ebd4570acd1;hb=c1a305b54c1a9dd1bfe2173940ba84ccd1b4bb27;hp=800d1efd4671eda0331dc8fa3a4044f71ad94768;hpb=9b0d1f04cca6a583d85553cab0bef197c2940e61;p=gdcm.git diff --git a/src/gdcmFileHelper.cxx b/src/gdcmFileHelper.cxx index 800d1efd..b61faace 100644 --- a/src/gdcmFileHelper.cxx +++ b/src/gdcmFileHelper.cxx @@ -4,8 +4,8 @@ Module: $RCSfile: gdcmFileHelper.cxx,v $ Language: C++ - Date: $Date: 2007/10/01 09:28:57 $ - Version: $Revision: 1.131 $ + Date: $Date: 2009/05/19 15:07:58 $ + Version: $Revision: 1.139 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -33,9 +33,15 @@ #include "gdcmDocEntryArchive.h" #include "gdcmDictSet.h" #include "gdcmOrientation.h" - + + + +#include // for transform? + #if defined(__BORLANDC__) - #include // for memset + #include // for memset + #include //for toupper + #include #endif #include @@ -45,11 +51,11 @@ These lines will be moved to the document-to-be 'User's Guide' -// To read an image, user needs a gdcm::File -gdcm::File *f = new gdcm::File(fileName); +// To read an image, user needs a GDCM_NAME_SPACE::File +GDCM_NAME_SPACE::File *f = new GDCM_NAME_SPACE::File(fileName); // or (advanced) : // user may also decide he doesn't want to load some parts of the header -gdcm::File *f = new gdcm::File(); +GDCM_NAME_SPACE::File *f = new GDCM_NAME_SPACE::File(); f->SetFileName(fileName); f->SetLoadMode(LD_NOSEQ); // or f->SetLoadMode(LD_NOSHADOW); // or @@ -61,8 +67,8 @@ f->Load(); // user can now check some values std::string v = f->GetEntryValue(groupNb,ElementNb); -// to get the pixels, user needs a gdcm::FileHelper -gdcm::FileHelper *fh = new gdcm::FileHelper(f); +// to get the pixels, user needs a GDCM_NAME_SPACE::FileHelper +GDCM_NAME_SPACE::FileHelper *fh = new GDCM_NAME_SPACE::FileHelper(f); // user may ask not to convert Palette (if any) to RGB uint8_t *pixels = fh->GetImageDataRaw(); @@ -71,8 +77,8 @@ int imageLength = fh->GetImageDataRawSize(); // He can now use the pixels, create a new image, ... uint8_t *userPixels = ... -//To re-write the image, user re-uses the gdcm::FileHelper -gdcm::File *fh = new gdcm::FileHelper(); +//To re-write the image, user re-uses the GDCM_NAME_SPACE::FileHelper +GDCM_NAME_SPACE::File *fh = new GDCM_NAME_SPACE::FileHelper(); fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB // (WriteMode is set) @@ -151,7 +157,7 @@ fh->Write(newFileName); ElementSet::WriteContent(fp, writetype); writes recursively all DataElements RestoreWrite(); - (moves back to the gdcm::File all the archived elements) + (moves back to the GDCM_NAME_SPACE::File all the archived elements) */ @@ -164,7 +170,7 @@ typedef std::map GroupHT; // Hash Table // Constructor / Destructor /** * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3 - * file (gdcm::File only deals with the ... header) + * file (GDCM_NAME_SPACE::File only deals with the ... header) * Opens (in read only and when possible) an existing file and checks * for DICOM compliance. Returns NULL on failure. * It will be up to the user to load the pixels into memory @@ -210,7 +216,7 @@ FileHelper::FileHelper(File *header) /** * \brief canonical destructor - * \note If the header (gdcm::File) was created by the FileHelper constructor, + * \note If the header (GDCM_NAME_SPACE::File) was created by the FileHelper constructor, * it is destroyed by the FileHelper */ FileHelper::~FileHelper() @@ -235,7 +241,7 @@ FileHelper::~FileHelper() // Public /** - * \brief Sets the LoadMode of the internal gdcm::File as a boolean string. + * \brief Sets the LoadMode of the internal GDCM_NAME_SPACE::File as a boolean string. * NO_SEQ, NO_SHADOW, NO_SHADOWSEQ ... (nothing more, right now) * WARNING : before using NO_SHADOW, be sure *all* your files * contain accurate values in the 0x0000 element (if any) @@ -247,7 +253,7 @@ void FileHelper::SetLoadMode(int loadMode) GetFile()->SetLoadMode( loadMode ); } /** - * \brief Sets the LoadMode of the internal gdcm::File + * \brief Sets the LoadMode of the internal GDCM_NAME_SPACE::File * @param fileName name of the file to be open */ void FileHelper::SetFileName(std::string const &fileName) @@ -727,7 +733,6 @@ bool FileHelper::Write(std::string const &fileName) { CheckMandatoryElements(); //called once, here ! - bool flag = false; switch(WriteType) { case ImplicitVR: @@ -870,7 +875,14 @@ bool FileHelper::CheckWriteIntegrity() if ( abs((long)(decSize-userDataSize))>1) // ignore padding zero { gdcmWarningMacro( "Data size (Raw) is incorrect. Should be " - << decSize << " / Found :" + << decSize << "(" + << FileInternal->GetXSize() << " * " + << FileInternal->GetYSize() << " * " + << FileInternal->GetZSize() << " * " + << FileInternal->GetTSize() << " * " + << FileInternal->GetSamplesPerPixel() << " * " + << numberBitsAllocated / 8 + << ") / Found :" << userDataSize ); return false; } @@ -1316,7 +1328,7 @@ We have to deal with 4 *very* different cases : -Probabely some more to be added. --> Set it with FileHelper::SetContentType(int); -gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases. +GDCM_NAME_SPACE::FileHelper::CheckMandatoryElements() deals automatically with these cases. 1)2)3)4) 0008 0012 Instance Creation Date @@ -1371,7 +1383,7 @@ If 'SOP Class UID' exists in the native image ('true DICOM' image) Bellow follows the full description (hope so !) of the consistency checks performed -by gdcm::FileHelper::CheckMandatoryElements() +by GDCM_NAME_SPACE::FileHelper::CheckMandatoryElements() -->'Media Storage SOP Class UID' (0x0002,0x0002) @@ -1505,46 +1517,75 @@ void FileHelper::CheckMandatoryElements() // --------------------- For DataSet --------------------- + // check whether 0018|0015 [CS] [Body Part Examined] value is UPPER CASE + // (avoid dciodvfy to complain!) + DataEntry *e_0018_0015 = FileInternal->GetDataEntry(0x0018, 0x0015); + if ( e_0018_0015) + { + std::string bodyPartExamined = e_0018_0015->GetString(); + std::transform(bodyPartExamined.begin(), bodyPartExamined.end(), bodyPartExamined.begin(), + (int(*)(int)) toupper); + CopyMandatoryEntry(0x0018,0x0015,bodyPartExamined,"CS"); + } + if ( ContentType != USER_OWN_IMAGE) // when it's not a user made image { // If 'SOP Class UID' and 'SOP Instance UID' exist ('true DICOM' image) // we create the 'Source Image Sequence' SeqEntry // to hold informations about the Source Image - + + // 'SOP Instance UID' DataEntry *e_0008_0016 = FileInternal->GetDataEntry(0x0008, 0x0016); + // DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018); if ( e_0008_0016 && e_0008_0018) { - // Create 'Source Image Sequence' SeqEntry - SeqEntry *sis = SeqEntry::New (0x0008, 0x2112); - SQItem *sqi = SQItem::New(1); + // Create 'Source Image Sequence' SeqEntry + SeqEntry *sis = SeqEntry::New (0x0008, 0x2112); + SQItem *sqi = SQItem::New(1); - // create 'Referenced SOP Class UID' from 'SOP Class UID' + // create 'Referenced SOP Class UID' from 'SOP Class UID' - DataEntry *e_0008_1150 = DataEntry::New(0x0008, 0x1150, "UI"); - e_0008_1150->SetString( e_0008_0016->GetString()); - sqi->AddEntry(e_0008_1150); - e_0008_1150->Delete(); + DataEntry *e_0008_1150 = DataEntry::New(0x0008, 0x1150, "UI"); + e_0008_1150->SetString( e_0008_0016->GetString()); + sqi->AddEntry(e_0008_1150); + e_0008_1150->Delete(); - // create 'Referenced SOP Instance UID' from 'SOP Instance UID' - DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018); + // create 'Referenced SOP Instance UID' from 'SOP Instance UID' + // DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018); - DataEntry *e_0008_1155 = DataEntry::New(0x0008, 0x1155, "UI"); - e_0008_1155->SetString( e_0008_0018->GetString()); - sqi->AddEntry(e_0008_1155); - e_0008_1155->Delete(); + DataEntry *e_0008_1155 = DataEntry::New(0x0008, 0x1155, "UI"); + e_0008_1155->SetString( e_0008_0018->GetString()); + sqi->AddEntry(e_0008_1155); + e_0008_1155->Delete(); - sis->AddSQItem(sqi,1); - sqi->Delete(); - - // temporarily replaces any previous 'Source Image Sequence' - Archive->Push(sis); - sis->Delete(); - // FIXME : is 'Image Type' *really* depending on the presence of 'SOP Class UID'? - if ( ContentType == FILTERED_IMAGE) - // the user *knows* he just modified the pixels - // the image is no longer an 'Original' one - CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY","CS"); + sis->AddSQItem(sqi,1); + sqi->Delete(); + + // temporarily replaces any previous 'Source Image Sequence' + Archive->Push(sis); + sis->Delete(); + // FIXME : is 'Image Type' *really* depending on the presence of 'SOP Class UID'? + + if ( ContentType == FILTERED_IMAGE) // the user *knows* he just modified the pixels + { + DataEntry *e_0008_0008 = FileInternal->GetDataEntry(0x0008, 0x0008); + if ( e_0008_0008) + { + std::string imageType = e_0008_0008->GetString(); + std::string::size_type p = imageType.find("ORIGINAL"); + if (p == 0) // image is ORIGINAL one + { + // the image is no longer an 'Original' one + CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY","CS"); + } + // if Image Type was not ORIGINAL\..., we keep it. + } + else // 0008_0008 was missing, wee add it. + { + CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY","CS"); + } + } } } @@ -1591,7 +1632,10 @@ void FileHelper::CheckMandatoryElements() std::ostringstream s; // check 'Bits Allocated' vs decent values int nbBitsAllocated = FileInternal->GetBitsAllocated(); - if ( (nbBitsAllocated == 0 || nbBitsAllocated > 32) + + // We allow now to deal with 'non standard' 64 bits 'real' values + + if ( (nbBitsAllocated == 0 || nbBitsAllocated > 64) // was 32 || ( nbBitsAllocated > 8 && nbBitsAllocated <16) ) { CopyMandatoryEntry(0x0028,0x0100,"16","US");