Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

gdcmFileHelper.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmFileHelper.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2005/02/09 18:35:30 $
00007   Version:   $Revision: 1.15 $
00008                                                                                 
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012                                                                                 
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016                                                                                 
00017 =========================================================================*/
00018 
00019 #include "gdcmFileHelper.h"
00020 #include "gdcmGlobal.h"
00021 #include "gdcmTS.h"
00022 #include "gdcmDocument.h"
00023 #include "gdcmDebug.h"
00024 #include "gdcmUtil.h"
00025 #include "gdcmBinEntry.h"
00026 #include "gdcmValEntry.h"
00027 #include "gdcmContentEntry.h"
00028 #include "gdcmFile.h"
00029 #include "gdcmPixelReadConvert.h"
00030 #include "gdcmPixelWriteConvert.h"
00031 #include "gdcmDocEntryArchive.h"
00032 
00033 #include <fstream>
00034 
00035 namespace gdcm 
00036 {
00037 //-------------------------------------------------------------------------
00038 // Constructor / Destructor
00051 FileHelper::FileHelper( )
00052 {
00053    FileInternal = new File( );
00054    SelfHeader = true;
00055    Initialize();
00056 }
00057 
00071 FileHelper::FileHelper(File *header)
00072 {
00073    FileInternal = header;
00074    SelfHeader = false;
00075    Initialize();
00076 }
00077 
00091 FileHelper::FileHelper(std::string const &filename )
00092 {
00093    FileInternal = new File( filename );
00094    SelfHeader = true;
00095    Initialize();
00096 }
00097 
00103 FileHelper::~FileHelper()
00104 { 
00105    if( PixelReadConverter )
00106    {
00107       delete PixelReadConverter;
00108    }
00109    if( PixelWriteConverter )
00110    {
00111       delete PixelWriteConverter;
00112    }
00113    if( Archive )
00114    {
00115       delete Archive;
00116    }
00117 
00118    if( SelfHeader )
00119    {
00120       delete FileInternal;
00121    }
00122    FileInternal = 0;
00123 }
00124 
00125 //-----------------------------------------------------------------------------
00126 // Public
00135 bool FileHelper::SetValEntry(std::string const &content,
00136                              uint16_t group, uint16_t elem)
00137 { 
00138    return FileInternal->SetValEntry(content,group,elem);
00139 }
00140 
00141 
00151 bool FileHelper::SetBinEntry(uint8_t *content, int lgth,
00152                              uint16_t group, uint16_t elem)
00153 {
00154    return FileInternal->SetBinEntry(content,lgth,group,elem);
00155 }
00156 
00166 ValEntry *FileHelper::InsertValEntry(std::string const &content,
00167                                      uint16_t group, uint16_t elem)
00168 {
00169    return FileInternal->InsertValEntry(content,group,elem);
00170 }
00171 
00183 BinEntry *FileHelper::InsertBinEntry(uint8_t *binArea, int lgth,
00184                                      uint16_t group, uint16_t elem)
00185 {
00186    return FileInternal->InsertBinEntry(binArea,lgth,group,elem);
00187 }
00188 
00198 SeqEntry *FileHelper::InsertSeqEntry(uint16_t group, uint16_t elem)
00199 {
00200    return FileInternal->InsertSeqEntry(group,elem);
00201 }
00202 
00211 size_t FileHelper::GetImageDataSize()
00212 {
00213    if ( PixelWriteConverter->GetUserData() )
00214    {
00215       return PixelWriteConverter->GetUserDataSize();
00216    }
00217 
00218    return PixelReadConverter->GetRGBSize();
00219 }
00220 
00228 size_t FileHelper::GetImageDataRawSize()
00229 {
00230    if ( PixelWriteConverter->GetUserData() )
00231    {
00232       return PixelWriteConverter->GetUserDataSize();
00233    }
00234 
00235    return PixelReadConverter->GetRawSize();
00236 }
00237 
00248 uint8_t *FileHelper::GetImageData()
00249 {
00250    if ( PixelWriteConverter->GetUserData() )
00251    {
00252       return PixelWriteConverter->GetUserData();
00253    }
00254 
00255    if ( ! GetRaw() )
00256    {
00257       // If the decompression failed nothing can be done.
00258       return 0;
00259    }
00260 
00261    if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
00262    {
00263       return PixelReadConverter->GetRGB();
00264    }
00265    else
00266    {
00267       // When no LUT or LUT conversion fails, return the Raw
00268       return PixelReadConverter->GetRaw();
00269    }
00270 }
00271 
00281 uint8_t *FileHelper::GetImageDataRaw ()
00282 {
00283    return GetRaw();
00284 }
00285 
00311 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
00312 {
00313    if ( ! GetRaw() )
00314    {
00315       // If the decompression failed nothing can be done.
00316       return 0;
00317    }
00318 
00319    if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
00320    {
00321       if ( PixelReadConverter->GetRGBSize() > maxSize )
00322       {
00323          gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
00324          return 0;
00325       }
00326       memcpy( destination,
00327               (void*)PixelReadConverter->GetRGB(),
00328               PixelReadConverter->GetRGBSize() );
00329       return PixelReadConverter->GetRGBSize();
00330    }
00331 
00332    // Either no LUT conversion necessary or LUT conversion failed
00333    if ( PixelReadConverter->GetRawSize() > maxSize )
00334    {
00335       gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
00336       return 0;
00337    }
00338    memcpy( destination,
00339            (void*)PixelReadConverter->GetRaw(),
00340            PixelReadConverter->GetRawSize() );
00341    return PixelReadConverter->GetRawSize();
00342 }
00343 
00359 void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
00360 {
00361    SetUserData(inData,expectedSize);
00362 }
00363 
00373 void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize)
00374 {
00375    PixelWriteConverter->SetUserData(inData,expectedSize);
00376 }
00377 
00382 uint8_t *FileHelper::GetUserData()
00383 {
00384    return PixelWriteConverter->GetUserData();
00385 }
00386 
00391 size_t FileHelper::GetUserDataSize()
00392 {
00393    return PixelWriteConverter->GetUserDataSize();
00394 }
00395 
00400 uint8_t *FileHelper::GetRGBData()
00401 {
00402    return PixelReadConverter->GetRGB();
00403 }
00404 
00409 size_t FileHelper::GetRGBDataSize()
00410 {
00411    return PixelReadConverter->GetRGBSize();
00412 }
00413 
00418 uint8_t *FileHelper::GetRawData()
00419 {
00420    return PixelReadConverter->GetRaw();
00421 }
00422 
00427 size_t FileHelper::GetRawDataSize()
00428 {
00429    return PixelReadConverter->GetRawSize();
00430 }
00431 
00435 uint8_t* FileHelper::GetLutRGBA()
00436 {
00437    return PixelReadConverter->GetLutRGBA();
00438 }
00439 
00448 bool FileHelper::WriteRawData(std::string const &fileName)
00449 {
00450   std::ofstream fp1(fileName.c_str(), std::ios::out | std::ios::binary );
00451    if (!fp1)
00452    {
00453       gdcmWarningMacro( "Fail to open (write) file:" << fileName.c_str());
00454       return false;
00455    }
00456 
00457    if( PixelWriteConverter->GetUserData() )
00458    {
00459       fp1.write( (char*)PixelWriteConverter->GetUserData(), 
00460                  PixelWriteConverter->GetUserDataSize() );
00461    }
00462    else if ( PixelReadConverter->GetRGB() )
00463    {
00464       fp1.write( (char*)PixelReadConverter->GetRGB(), 
00465                  PixelReadConverter->GetRGBSize());
00466    }
00467    else if ( PixelReadConverter->GetRaw() )
00468    {
00469       fp1.write( (char*)PixelReadConverter->GetRaw(), 
00470                  PixelReadConverter->GetRawSize());
00471    }
00472    else
00473    {
00474       gdcmErrorMacro( "Nothing written." );
00475    }
00476 
00477    fp1.close();
00478 
00479    return true;
00480 }
00481 
00491 bool FileHelper::WriteDcmImplVR (std::string const &fileName)
00492 {
00493    SetWriteTypeToDcmImplVR();
00494    return Write(fileName);
00495 }
00496 
00506 bool FileHelper::WriteDcmExplVR (std::string const &fileName)
00507 {
00508    SetWriteTypeToDcmExplVR();
00509    return Write(fileName);
00510 }
00511 
00526 bool FileHelper::WriteAcr (std::string const &fileName)
00527 {
00528    SetWriteTypeToAcr();
00529    return Write(fileName);
00530 }
00531 
00538 bool FileHelper::Write(std::string const &fileName)
00539 {
00540    switch(WriteType)
00541    {
00542       case ImplicitVR:
00543          SetWriteFileTypeToImplicitVR();
00544          break;
00545       case ExplicitVR:
00546          SetWriteFileTypeToExplicitVR();
00547          break;
00548       case ACR:
00549       case ACR_LIBIDO:
00550          SetWriteFileTypeToACR();
00551          break;
00552       default:
00553          SetWriteFileTypeToExplicitVR();
00554    }
00555 
00556    // --------------------------------------------------------------
00557    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
00558    //
00559    // if recognition code tells us we dealt with a LibIDO image
00560    // we reproduce on disk the switch between lineNumber and columnNumber
00561    // just before writting ...
00564    if( WriteType == ACR_LIBIDO )
00565    {
00566       SetWriteToLibido();
00567    }
00568    else
00569    {
00570       SetWriteToNoLibido();
00571    }
00572    // ----------------- End of Special Patch ----------------
00573   
00574    switch(WriteMode)
00575    {
00576       case WMODE_RAW :
00577          SetWriteToRaw();
00578          break;
00579       case WMODE_RGB :
00580          SetWriteToRGB();
00581          break;
00582    }
00583 
00584    bool check = CheckWriteIntegrity();
00585    if(check)
00586    {
00587       check = FileInternal->Write(fileName,WriteType);
00588    }
00589 
00590    RestoreWrite();
00591    RestoreWriteFileType();
00592 
00593    // --------------------------------------------------------------
00594    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
00595    // 
00596    // ...and we restore the header to be Dicom Compliant again 
00597    // just after writting
00598    RestoreWriteOfLibido();
00599    // ----------------- End of Special Patch ----------------
00600 
00601    return check;
00602 }
00603 
00604 //-----------------------------------------------------------------------------
00605 // Protected
00614 bool FileHelper::CheckWriteIntegrity()
00615 {
00616    if(PixelWriteConverter->GetUserData())
00617    {
00618       int numberBitsAllocated = FileInternal->GetBitsAllocated();
00619       if ( numberBitsAllocated == 0 || numberBitsAllocated == 12 )
00620       {
00621          numberBitsAllocated = 16;
00622       }
00623 
00624       size_t decSize = FileInternal->GetXSize()
00625                     * FileInternal->GetYSize() 
00626                     * FileInternal->GetZSize()
00627                     * ( numberBitsAllocated / 8 )
00628                     * FileInternal->GetSamplesPerPixel();
00629       size_t rgbSize = decSize;
00630       if( FileInternal->HasLUT() )
00631          rgbSize = decSize * 3;
00632 
00633       switch(WriteMode)
00634       {
00635          case WMODE_RAW :
00636             if( decSize!=PixelWriteConverter->GetUserDataSize() )
00637             {
00638                gdcmWarningMacro( "Data size (Raw) is incorrect. Should be " 
00639                            << decSize << " / Found :" 
00640                            << PixelWriteConverter->GetUserDataSize() );
00641                return false;
00642             }
00643             break;
00644          case WMODE_RGB :
00645             if( rgbSize!=PixelWriteConverter->GetUserDataSize() )
00646             {
00647                gdcmWarningMacro( "Data size (RGB) is incorrect. Should be " 
00648                           << decSize << " / Found " 
00649                           << PixelWriteConverter->GetUserDataSize() );
00650                return false;
00651             }
00652             break;
00653       }
00654    }
00655    
00656    return true;
00657 }
00658 
00662 void FileHelper::SetWriteToRaw()
00663 {
00664    if( FileInternal->GetNumberOfScalarComponents() == 3 
00665     && !FileInternal->HasLUT())
00666    {
00667       SetWriteToRGB();
00668    } 
00669    else
00670    {
00671       ValEntry *photInt = CopyValEntry(0x0028,0x0004);
00672       if(FileInternal->HasLUT())
00673       {
00674          photInt->SetValue("PALETTE COLOR ");
00675       }
00676       else
00677       {
00678          photInt->SetValue("MONOCHROME1 ");
00679       }
00680 
00681       PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
00682                                        PixelReadConverter->GetRawSize());
00683 
00684       std::string vr = "OB";
00685       if( FileInternal->GetBitsAllocated()>8 )
00686          vr = "OW";
00687       if( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files 
00688          vr = "OB";
00689       BinEntry *pixel = 
00690          CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
00691       pixel->SetValue(GDCM_BINLOADED);
00692       pixel->SetBinArea(PixelWriteConverter->GetData(),false);
00693       pixel->SetLength(PixelWriteConverter->GetDataSize());
00694 
00695       Archive->Push(photInt);
00696       Archive->Push(pixel);
00697    }
00698 }
00699 
00703 void FileHelper::SetWriteToRGB()
00704 {
00705    if(FileInternal->GetNumberOfScalarComponents()==3)
00706    {
00707       PixelReadConverter->BuildRGBImage();
00708       
00709       ValEntry *spp = CopyValEntry(0x0028,0x0002);
00710       spp->SetValue("3 ");
00711 
00712       ValEntry *planConfig = CopyValEntry(0x0028,0x0006);
00713       planConfig->SetValue("0 ");
00714 
00715       ValEntry *photInt = CopyValEntry(0x0028,0x0004);
00716       photInt->SetValue("RGB ");
00717 
00718       if(PixelReadConverter->GetRGB())
00719       {
00720          PixelWriteConverter->SetReadData(PixelReadConverter->GetRGB(),
00721                                           PixelReadConverter->GetRGBSize());
00722       }
00723       else // Raw data
00724       {
00725          PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
00726                                           PixelReadConverter->GetRawSize());
00727       }
00728 
00729       std::string vr = "OB";
00730       if( FileInternal->GetBitsAllocated()>8 )
00731          vr = "OW";
00732       if( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files 
00733          vr = "OB";
00734       BinEntry *pixel = 
00735          CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
00736       pixel->SetValue(GDCM_BINLOADED);
00737       pixel->SetBinArea(PixelWriteConverter->GetData(),false);
00738       pixel->SetLength(PixelWriteConverter->GetDataSize());
00739 
00740       Archive->Push(spp);
00741       Archive->Push(planConfig);
00742       Archive->Push(photInt);
00743       Archive->Push(pixel);
00744 
00745       // Remove any LUT
00746       Archive->Push(0x0028,0x1101);
00747       Archive->Push(0x0028,0x1102);
00748       Archive->Push(0x0028,0x1103);
00749       Archive->Push(0x0028,0x1201);
00750       Archive->Push(0x0028,0x1202);
00751       Archive->Push(0x0028,0x1203);
00752 
00753       // For old ACR-NEMA
00754       // Thus, we have a RGB image and the bits allocated = 24 and 
00755       // samples per pixels = 1 (in the read file)
00756       if(FileInternal->GetBitsAllocated()==24) 
00757       {
00758          ValEntry *bitsAlloc = CopyValEntry(0x0028,0x0100);
00759          bitsAlloc->SetValue("8 ");
00760 
00761          ValEntry *bitsStored = CopyValEntry(0x0028,0x0101);
00762          bitsStored->SetValue("8 ");
00763 
00764          ValEntry *highBit = CopyValEntry(0x0028,0x0102);
00765          highBit->SetValue("7 ");
00766 
00767          Archive->Push(bitsAlloc);
00768          Archive->Push(bitsStored);
00769          Archive->Push(highBit);
00770       }
00771    }
00772    else
00773    {
00774       SetWriteToRaw();
00775    }
00776 }
00777 
00781 void FileHelper::RestoreWrite()
00782 {
00783    Archive->Restore(0x0028,0x0002);
00784    Archive->Restore(0x0028,0x0004);
00785    Archive->Restore(0x0028,0x0006);
00786    Archive->Restore(GetFile()->GetGrPixel(),GetFile()->GetNumPixel());
00787 
00788    // For old ACR-NEMA (24 bits problem)
00789    Archive->Restore(0x0028,0x0100);
00790    Archive->Restore(0x0028,0x0101);
00791    Archive->Restore(0x0028,0x0102);
00792 
00793    // For the LUT
00794    Archive->Restore(0x0028,0x1101);
00795    Archive->Restore(0x0028,0x1102);
00796    Archive->Restore(0x0028,0x1103);
00797    Archive->Restore(0x0028,0x1201);
00798    Archive->Restore(0x0028,0x1202);
00799    Archive->Restore(0x0028,0x1203);
00800 }
00801 
00805 void FileHelper::SetWriteFileTypeToACR()
00806 {
00807    Archive->Push(0x0002,0x0010);
00808 }
00809 
00813 void FileHelper::SetWriteFileTypeToExplicitVR()
00814 {
00815    std::string ts = Util::DicomString( 
00816       Global::GetTS()->GetSpecialTransferSyntax(TS::ExplicitVRLittleEndian) );
00817 
00818    ValEntry *tss = CopyValEntry(0x0002,0x0010);
00819    tss->SetValue(ts);
00820 
00821    Archive->Push(tss);
00822 }
00823 
00827 void FileHelper::SetWriteFileTypeToImplicitVR()
00828 {
00829    std::string ts = Util::DicomString(
00830       Global::GetTS()->GetSpecialTransferSyntax(TS::ImplicitVRLittleEndian) );
00831 
00832    ValEntry *tss = CopyValEntry(0x0002,0x0010);
00833    tss->SetValue(ts);
00834 
00835    Archive->Push(tss);
00836 }
00837 
00838 
00842 void FileHelper::RestoreWriteFileType()
00843 {
00844    Archive->Restore(0x0002,0x0010);
00845 }
00846 
00850 void FileHelper::SetWriteToLibido()
00851 {
00852    ValEntry *oldRow = dynamic_cast<ValEntry *>
00853                 (FileInternal->GetDocEntry(0x0028, 0x0010));
00854    ValEntry *oldCol = dynamic_cast<ValEntry *>
00855                 (FileInternal->GetDocEntry(0x0028, 0x0011));
00856    
00857    if( oldRow && oldCol )
00858    {
00859       std::string rows, columns; 
00860 
00861       ValEntry *newRow=new ValEntry(oldRow->GetDictEntry());
00862       ValEntry *newCol=new ValEntry(oldCol->GetDictEntry());
00863 
00864       newRow->Copy(oldCol);
00865       newCol->Copy(oldRow);
00866 
00867       newRow->SetValue(oldCol->GetValue());
00868       newCol->SetValue(oldRow->GetValue());
00869 
00870       Archive->Push(newRow);
00871       Archive->Push(newCol);
00872    }
00873 
00874    ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
00875    libidoCode->SetValue("ACRNEMA_LIBIDO_1.1");
00876    Archive->Push(libidoCode);
00877 }
00878 
00882 void FileHelper::SetWriteToNoLibido()
00883 {
00884    ValEntry *recCode = dynamic_cast<ValEntry *>
00885                 (FileInternal->GetDocEntry(0x0008,0x0010));
00886    if( recCode )
00887    {
00888       if( recCode->GetValue() == "ACRNEMA_LIBIDO_1.1" )
00889       {
00890          ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
00891          libidoCode->SetValue("");
00892          Archive->Push(libidoCode);
00893       }
00894    }
00895 }
00896 
00900 void FileHelper::RestoreWriteOfLibido()
00901 {
00902    Archive->Restore(0x0028,0x0010);
00903    Archive->Restore(0x0028,0x0011);
00904    Archive->Restore(0x0008,0x0010);
00905 }
00906 
00914 ValEntry *FileHelper::CopyValEntry(uint16_t group,uint16_t elem)
00915 {
00916    DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
00917    ValEntry *newE;
00918 
00919    if( oldE )
00920    {
00921       newE = new ValEntry(oldE->GetDictEntry());
00922       newE->Copy(oldE);
00923    }
00924    else
00925    {
00926       newE = GetFile()->NewValEntry(group,elem);
00927    }
00928 
00929    return newE;
00930 }
00931 
00941 BinEntry *FileHelper::CopyBinEntry(uint16_t group,uint16_t elem,
00942                       const std::string &vr)
00943 {
00944    DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
00945    BinEntry *newE;
00946 
00947    if( oldE )
00948       if( oldE->GetVR()!=vr )
00949          oldE = NULL;
00950 
00951    if( oldE )
00952    {
00953       newE = new BinEntry(oldE->GetDictEntry());
00954       newE->Copy(oldE);
00955    }
00956    else
00957    {
00958       newE = GetFile()->NewBinEntry(group,elem,vr);
00959    }
00960 
00961    return newE;
00962 }
00963 
00964 //-----------------------------------------------------------------------------
00965 // Private
00969 void FileHelper::Initialize()
00970 {
00971    WriteMode = WMODE_RAW;
00972    WriteType = ExplicitVR;
00973 
00974    PixelReadConverter = new PixelReadConvert;
00975    PixelWriteConverter = new PixelWriteConvert;
00976    Archive = new DocEntryArchive( FileInternal );
00977 
00978    if ( FileInternal->IsReadable() )
00979    {
00980       PixelReadConverter->GrabInformationsFromFile( FileInternal );
00981    }
00982 }
00983 
00987 uint8_t *FileHelper::GetRaw()
00988 {
00989    uint8_t *raw = PixelReadConverter->GetRaw();
00990    if ( ! raw )
00991    {
00992       // The Raw image migth not be loaded yet:
00993       std::ifstream *fp = FileInternal->OpenFile();
00994       PixelReadConverter->ReadAndDecompressPixelData( fp );
00995       if(fp) 
00996          FileInternal->CloseFile();
00997 
00998       raw = PixelReadConverter->GetRaw();
00999       if ( ! raw )
01000       {
01001          gdcmWarningMacro( "Read/decompress of pixel data apparently went wrong.");
01002          return 0;
01003       }
01004    }
01005 
01006    return raw;
01007 }
01008 
01009 //-----------------------------------------------------------------------------
01010 // Print
01011 void FileHelper::Print(std::ostream &os, std::string const &)
01012 {
01013    FileInternal->SetPrintLevel(PrintLevel);
01014    FileInternal->Print(os);
01015 
01016    PixelReadConverter->SetPrintLevel(PrintLevel);
01017    PixelReadConverter->Print(os);
01018 }
01019 
01020 //-----------------------------------------------------------------------------
01021 } // end namespace gdcm

Generated on Thu Feb 10 22:17:58 2005 for gdcm by doxygen 1.3.6