X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmFileHelper.cxx;h=7183e58967f6c7fd83d8e7bfc12c31993673edb3;hb=76b3dc477f0e176f91ea991d7a951a863bab3247;hp=687d43ca6c37989e136b74e5a92cf6f170336436;hpb=96a20c8aafd6b3e9dc558d6642d2eaf53edf0dd0;p=gdcm.git diff --git a/src/gdcmFileHelper.cxx b/src/gdcmFileHelper.cxx index 687d43ca..7183e589 100644 --- a/src/gdcmFileHelper.cxx +++ b/src/gdcmFileHelper.cxx @@ -4,8 +4,8 @@ Module: $RCSfile: gdcmFileHelper.cxx,v $ Language: C++ - Date: $Date: 2006/05/02 13:11:57 $ - Version: $Revision: 1.103 $ + Date: $Date: 2006/10/18 13:40:18 $ + Version: $Revision: 1.110 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -283,6 +283,7 @@ DataEntry *FileHelper::InsertEntryString(std::string const &content, * @param lgth new value length * @param group Group number of the Entry * @param elem Element number of the Entry + * @param vr Value Represenation of the DataElement to be inserted * \return pointer to the modified/created DataEntry (NULL when creation * failed). */ @@ -391,7 +392,7 @@ uint8_t *FileHelper::GetImageDataRaw () return GetRaw(); } -#ifndef GDCM_LEGACY_REMOVE +//#ifndef GDCM_LEGACY_REMOVE /* * \brief Useless function, since PixelReadConverter forces us * copy the Pixels anyway. @@ -418,6 +419,7 @@ uint8_t *FileHelper::GetImageDataRaw () * @return On success, the number of bytes actually copied. Zero on * failure e.g. MaxSize is lower than necessary. */ + /* size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize) { if ( ! GetRaw() ) @@ -450,7 +452,8 @@ size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize) PixelReadConverter->GetRawSize() ); return PixelReadConverter->GetRawSize(); } -#endif +*/ +//#endif /** * \brief Points the internal pointer to the callers inData @@ -705,7 +708,7 @@ bool FileHelper::Write(std::string const &fileName) } break; - SetWriteFileTypeToExplicitVR(); // to see JPRx + SetWriteFileTypeToExplicitVR(); // to see JPRx break; case ACR: case ACR_LIBIDO: @@ -726,8 +729,12 @@ bool FileHelper::Write(std::string const &fileName) case JPEG: SetWriteFileTypeToJPEG(); break; + + case JPEG2000: + SetWriteFileTypeToJPEG2000(); + break; } - + // -------------------------------------------------------------- // Special Patch to allow gdcm to re-write ACR-LibIDO formated images // @@ -758,7 +765,7 @@ bool FileHelper::Write(std::string const &fileName) } bool check = CheckWriteIntegrity(); // verifies length - if (WriteType == JPEG ) check = true; + if (WriteType == JPEG || WriteType == JPEG2000) check = true; if (check) { check = FileInternal->Write(fileName,WriteType); @@ -871,6 +878,11 @@ void FileHelper::SetWriteToRaw() vr = "OW"; if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files vr = "OB"; + // For non RAW data. Mainly JPEG + if( WriteType == JPEG || WriteType == JPEG2000) + { + vr = "OW"; + } DataEntry *pixel = CopyDataEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr); pixel->SetFlag(DataEntry::FLAG_PIXELDATA); @@ -1042,6 +1054,21 @@ void FileHelper::SetWriteFileTypeToACR() Archive->Push(0x0002,0x0102); } + /** + * \brief Sets in the File the TransferSyntax to 'JPEG2000' + */ +void FileHelper::SetWriteFileTypeToJPEG2000() +{ + std::string ts = Util::DicomString( + Global::GetTS()->GetSpecialTransferSyntax(TS::JPEG2000Lossless) ); + + DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI"); + tss->SetString(ts); + + Archive->Push(tss); + tss->Delete(); +} + /** * \brief Sets in the File the TransferSyntax to 'JPEG' */ @@ -1388,6 +1415,11 @@ void FileHelper::CheckMandatoryElements() //0002 0016 AE 1 Source Application Entity Title //0002 0100 UI 1 Private Information Creator //0002 0102 OB 1 Private Information + + // Push out 'ACR-NEMA-special' entries, if any + Archive->Push(0x0008,0x0001); // Length to End + Archive->Push(0x0008,0x0010); // Recognition Code + Archive->Push(0x0028,0x0005); // Image Dimension // Create them if not found // Always modify the value @@ -1500,6 +1532,8 @@ void FileHelper::CheckMandatoryElements() // Replace deprecated 0028 0012 US Planes // by new 0028 0008 IS Number of Frames + + ///\todo : find if there is a rule! DataEntry *e_0028_0012 = FileInternal->GetDataEntry(0x0028, 0x0012); if ( e_0028_0012 ) { @@ -1519,7 +1553,8 @@ void FileHelper::CheckMandatoryElements() std::ostringstream s; // check 'Bits Allocated' vs decent values int nbBitsAllocated = FileInternal->GetBitsAllocated(); - if ( nbBitsAllocated == 0 || nbBitsAllocated > 32) + if ( nbBitsAllocated == 0 || nbBitsAllocated > 32 + || ( nbBitsAllocated > 8 && nbBitsAllocated <16) ) { CopyMandatoryEntry(0x0028,0x0100,"16","US"); gdcmWarningMacro("(0028,0100) changed from " @@ -1552,6 +1587,24 @@ void FileHelper::CheckMandatoryElements() << " for consistency purpose"); } + // check Pixel Representation (default it as 0 -unsigned-) + + DataEntry *e_0028_0103 = FileInternal->GetDataEntry(0x0028, 0x0103); + if ( !e_0028_0103 ) + { + gdcmWarningMacro("PixelRepresentation (0028,0103) is supposed to be mandatory"); + CopyMandatoryEntry(0x0028, 0x0103,"0","US"); + } + else + { + int sign = (int)e_0028_0103->GetValue(0); + if (sign !=1 && sign !=0) + { + gdcmWarningMacro("PixelRepresentation (0028,0103) is supposed to be =1 or =0"); + CopyMandatoryEntry(0x0028, 0x0103,"0","US"); + } + } + std::string pixelSpacing = FileInternal->GetEntryString(0x0028,0x0030); if ( pixelSpacing == GDCM_UNFOUND ) { @@ -1566,7 +1619,56 @@ void FileHelper::CheckMandatoryElements() // we write it only when we are *sure* the image comes from // an imager (see also 0008,0x0064) CheckMandatoryEntry(0x0018,0x1164,pixelSpacing,"DS"); + + + +/* +///Exact meaning of RETired fields + +// See page 73 of ACR-NEMA_300-1988.pdf ! + +// 0020,0020 : Patient Orientation : +Patient direction of the first row and +column of the images. The first entry id the direction of the raws, given by the +direction of the last pixel in the first row from the first pixel in tha row. +the second entry is the direction of the columns, given by the direction of the +last pixel in the first column from the first pixel in that column. +L : Left, F : Feet, A : Anterior, P : Posterior. +Up to 3 letters can be used in combination to indicate oblique planes. + +//0020,0030 Image Position (RET) +x,y,z coordinates im mm of the first pixel in the image + +// 0020,0035 Image Orientation (RET) +Direction cosines of the R axis of the image system with respect to the +equipment coordinate axes x,y,z, followed by direction cosines of the C axis of +the image system with respect to the same axes + +//0020,0050 Location +An image location reference, standard for the modality (such as CT bed +position), used to indicate position. Calculation of position for other purposes +is only from (0020,0030) and (0020,0035) +*/ + +/* +// if imagePositionPatient not found, default it with imagePositionRet, if any +// if imageOrientationPatient not found, default it with imageOrientationRet, if any + + std::string imagePositionRet = FileInternal->GetEntryString(0x0020,0x0030); + std::string imageOrientationRet = FileInternal->GetEntryString(0x0020,0x0035); + std::string imagePositionPatient = FileInternal->GetEntryString(0x0020,0x0032); + std::string imageOrientationPatient = FileInternal->GetEntryString(0x0020,0x0037); + if( imagePositionPatient == GDCM_UNFOUND && imageOrientationPatient == GDCM_UNFOUND + && imagePositionRet != GDCM_UNFOUND && imageOrientationRet != GDCM_UNFOUND) + { + CopyMandatoryEntry(0x0020, 0x0032,imagePositionRet,"DS"); + Archive->Push(0x0020,0x0030); + CopyMandatoryEntry(0x0020, 0x0037,imageOrientationRet,"DS"); + Archive->Push(0x0020,0x0035); + } +*/ + // Samples Per Pixel (type 1) : default to grayscale CheckMandatoryEntry(0x0028,0x0002,"1","US"); @@ -1881,3 +1983,155 @@ void FileHelper::Print(std::ostream &os, std::string const &) //----------------------------------------------------------------------------- } // end namespace gdcm + + +/* Probabely something to be added to use Rescale Slope/Intercept +Have a look ,at ITK code ! + +// Internal function to rescale pixel according to Rescale Slope/Intercept +template +void RescaleFunction(TBuffer* buffer, TSource *source, + double slope, double intercept, size_t size) +{ + size /= sizeof(TSource); + + if (slope != 1.0 && intercept != 0.0) + { + // Duff's device. Instead of this code: + // + // for(unsigned int i=0; i 0); + } + } + else if (slope == 1.0 && intercept != 0.0) + { + // Duff's device. Instead of this code: + // + // for(unsigned int i=0; i 0); + } + } + else if (slope != 1.0 && intercept == 0.0) + { + // Duff's device. Instead of this code: + // + // for(unsigned int i=0; i 0); + } + } + else + { + // Duff's device. Instead of this code: + // + // for(unsigned int i=0; i 0); + } + } + + +} + + +template +void RescaleFunction(ImageIOBase::IOComponentType bufferType, + void* buffer, TSource *source, + double slope, double intercept, size_t size) +{ + switch (bufferType) + { + case ImageIOBase::UCHAR: + RescaleFunction( (unsigned char *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::CHAR: + RescaleFunction( (char *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::USHORT: + RescaleFunction( (unsigned short *)buffer, source, slope, intercept,size); + break; + case ImageIOBase::SHORT: + RescaleFunction( (short *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::UINT: + RescaleFunction( (unsigned int *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::INT: + RescaleFunction( (int *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::FLOAT: + RescaleFunction( (float *)buffer, source, slope, intercept, size); + break; + case ImageIOBase::DOUBLE: + RescaleFunction( (double *)buffer, source, slope, intercept, size); + break; + default: + ::itk::OStringStream message; + message << "itk::ERROR: GDCMImageIO: Unknown component type : " << bufferType; + ::itk::ExceptionObject e(__FILE__, __LINE__, message.str().c_str(),ITK_LOCATION); + throw e; + } +} +*/