Module: $RCSfile: gdcmFileHelper.cxx,v $
Language: C++
- Date: $Date: 2007/08/21 12:51:09 $
- Version: $Revision: 1.120 $
+ Date: $Date: 2007/08/31 14:11:00 $
+ Version: $Revision: 1.126 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
// to get the pixels, user needs a gdcm::FileHelper
gdcm::FileHelper *fh = new gdcm::FileHelper(f);
+
// user may ask not to convert Palette (if any) to RGB
uint8_t *pixels = fh->GetImageDataRaw();
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
+//To re-write the image, user re-uses the gdcm::FileHelper
+gdcm::File *fh = new gdcm::FileHelper();
-fh->SetImageData( userPixels, userPixelsLength);
fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
// (WriteMode is set)
fh->SetPhotometricInterpretationToMonochrome1();
fh->SetWriteTypeToDcmExpl(); // he wants Explicit Value Representation
- // Little Endian is the default
- // no other value is allowed
+ // Little Endian is the default,
+ // bigendian not supported for writting
(-->SetWriteType(ExplicitVR);)
-->WriteType = ExplicitVR;
+fh->SetWriteTypeToJPEG(); // lossless compression
+fh->SetWriteTypeToJPEG2000(); // lossless compression
+
+fh->SetImageData( userPixels, userPixelsLength);
+or
+fh->SetUserData( userPixels, userPixelsLength); // this one performs compression, when required
+
fh->Write(newFileName); // overwrites the file, if any
-// or :
-fh->WriteDcmExplVR(newFileName);
-// ----------------------------- WARNING -------------------------
These lines will be moved to the document-to-be 'Developer's Guide'
WriteType : ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO
PhotometricInterpretation : MONOCHROME2 (0=black), MONOCHROME2 (0=white)
-
+fh->SetImageData( userPixels, userPixelsLength);
+or
+fh->SetUserData( userPixels, userPixelsLength);
+ PixelWriteConverter->SetUserData(inData, expectedSize);
+
+
fh->SetWriteMode(WMODE_RAW / WMODE_RGB)
fh->SetWriteType( ImplicitVR/ExplicitVR/ACR/ACR_LIBIDO/JPEG/JPEG2000)
* not to deallocate its data before gdcm uses them (e.g. with
* the Write() method )
* @param inData user supplied pixel area (uint8_t* is just for the compiler.
- * user is allowed to pass any kind of pixelsn since the size is
+ * user is allowed to pass any kind of pixels since the size is
* given in bytes)
* @param expectedSize total image size, *in Bytes*
*/
void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
{
PixelWriteConverter->SetUserData(inData, expectedSize);
+ /// \todo : shouldn't we call SetCompressJPEGUserData/SetCompressJPEG2000UserData
+ /// here, too?
}
/**
*/
void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize)
{
+ // Shouldn't we move theese lines to FileHelper::Write()?
+/*
if( WriteType == JPEG2000 )
{
PixelWriteConverter->SetCompressJPEG2000UserData(inData, expectedSize, FileInternal);
{
PixelWriteConverter->SetUserData(inData, expectedSize);
}
+ */
+ // Just try!
+ PixelWriteConverter->SetUserData(inData, expectedSize);
}
/**
* @return false if write fails
*/
bool FileHelper::Write(std::string const &fileName)
-{
+{
CheckMandatoryElements(); //called once, here !
bool flag = false;
case Unknown: // should never happen; ExplicitVR is the default value
case ExplicitVR:
-
- // User should ask gdcm to write an image in Explicit VR mode
- // only when he is sure *all* the VR of *all* the DataElements is known.
- // i.e : when there are *only* Public Groups
- // or *all* the Shadow Groups are fully described in the relevant Shadow
- // Dictionnary
- // Let's just *dream* about it; *never* trust a user !
- // We turn to Implicit VR if at least the VR of one element is unknown.
- // Better we let DocEntry::WriteContent to put vr=UN for undocumented Shadow Groups !
-
-/*
- e = FileInternal->GetFirstEntry();
- while (e != 0)
- {
- if (e->GetVR() == " ")
- {
- SetWriteTypeToDcmImplVR();
- SetWriteFileTypeToImplicitVR();
- flag = true;
- break;
- }
- e = FileInternal->GetNextEntry();
- }
-
- if (!flag)
- {
- SetWriteFileTypeToExplicitVR();
- }
- break;
-*/
-
+ // We let DocEntry::WriteContent to put vr=UN for undocumented Shadow Groups !
SetWriteFileTypeToExplicitVR();
break;
// SetWriteFileTypeToImplicitVR(); // ACR IS implicit VR !
break;
- /// \todo FIXME : JPEG may be either ExplicitVR or ImplicitVR
+ /// \todo FIXME : JPEG/JPEG2000 may be either ExplicitVR or ImplicitVR
case JPEG:
SetWriteFileTypeToJPEG();
+ // was :
+ //PixelWriteConverter->SetCompressJPEGUserData(
+ // inData, expectedSize, FileInternal);
+ PixelWriteConverter->SetCompressJPEGUserData(
+ PixelWriteConverter->GetUserData(),
+ PixelWriteConverter->GetUserDataSize(),FileInternal);
break;
case JPEG2000:
+ /// \TODO Maybe we should consider doing the compression here !
+ // PixelWriteConverter->SetCompressJPEG2000UserData(inData, expectedSize, FileInternal);
+
SetWriteFileTypeToJPEG2000();
+ PixelWriteConverter->SetCompressJPEG2000UserData(
+ PixelWriteConverter->GetUserData(),
+ PixelWriteConverter->GetUserDataSize(),
+ FileInternal);
break;
}
break;
}
- bool check = CheckWriteIntegrity(); // verifies length
+ bool check;
if (WriteType == JPEG || WriteType == JPEG2000)
check = true;
+ else
+ check = CheckWriteIntegrity(); // verifies length
if (check)
{
int numberBitsAllocated = FileInternal->GetBitsAllocated();
if ( numberBitsAllocated == 0 || numberBitsAllocated == 12 )
{
- gdcmWarningMacro( "numberBitsAllocated changed from "
- << numberBitsAllocated << " to 16 "
+ gdcmWarningMacro( "numberBitsAllocated changed from "
+ << numberBitsAllocated << " to 16 "
<< " for consistency purpose" );
numberBitsAllocated = 16;
}
size_t decSize = FileInternal->GetXSize()
- * FileInternal->GetYSize()
+ * FileInternal->GetYSize()
* FileInternal->GetZSize()
* FileInternal->GetTSize()
* FileInternal->GetSamplesPerPixel()
if ( FileInternal->HasLUT() )
rgbSize = decSize * 3;
+ size_t userDataSize = PixelWriteConverter->GetUserDataSize();
switch(WriteMode)
{
case WMODE_RAW :
- if ( decSize!=PixelWriteConverter->GetUserDataSize() )
+ if ( abs(decSize-userDataSize)>1) // ignore padding zero
{
gdcmWarningMacro( "Data size (Raw) is incorrect. Should be "
<< decSize << " / Found :"
- << PixelWriteConverter->GetUserDataSize() );
+ << userDataSize );
return false;
}
break;
case WMODE_RGB :
- if ( rgbSize!=PixelWriteConverter->GetUserDataSize() )
+ if ( abs(rgbSize-userDataSize)>1) // ignore padding zero
{
gdcmWarningMacro( "Data size (RGB) is incorrect. Should be "
- << decSize << " / Found "
- << PixelWriteConverter->GetUserDataSize() );
+ << rgbSize << " / Found "
+ << userDataSize );
return false;
}
break;
* (modifies, when necessary, photochromatic interpretation,
* bits allocated, Pixels element VR)
* WARNING : if SetPhotometricInterpretationToMonochrome1() was called
- * before Pixel Elements if modified :-(
+ * before Pixel Elements is modified :-(
*/
void FileHelper::SetWriteToRaw()
{
vr = "OW";
if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files
vr = "OB";
- // For non RAW data. Mainly JPEG
+ // For non RAW data. Mainly JPEG/JPEG2000
if( WriteType == JPEG || WriteType == JPEG2000)
{
vr = "OW";
PixelReadConverter->BuildRGBImage();
DataEntry *spp = CopyDataEntry(0x0028,0x0002,"US");
- spp->SetString("3 ");
+ spp->SetString("3 "); // Don't drop trailing space
DataEntry *planConfig = CopyDataEntry(0x0028,0x0006,"US");
- planConfig->SetString("0 ");
+ planConfig->SetString("0 "); // Don't drop trailing space
DataEntry *photInt = CopyDataEntry(0x0028,0x0004,"CS");
- photInt->SetString("RGB ");
+ photInt->SetString("RGB "); // Don't drop trailing space
if ( PixelReadConverter->GetRGB() )
{
-4) user modified/added some tags *without processing* the pixels (anonymization...)
UNMODIFIED_PIXELS_IMAGE
-Probabely some more to be added.
+ --> Set it with FileHelper::SetContentType(int);
gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
if ( ContentType != USER_OWN_IMAGE) // when it's not a user made image
{
-
- gdcmDebugMacro( "USER_OWN_IMAGE (1)");
- // If 'SOP Class UID' exists ('true DICOM' 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
DataEntry *e_0008_0016 = FileInternal->GetDataEntry(0x0008, 0x0016);
- if ( e_0008_0016 )
+ DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018);
+ if ( e_0008_0016 && e_0008_0018)
{
// Create 'Source Image Sequence' SeqEntry
-// SeqEntry *sis = SeqEntry::New (
-// Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
SeqEntry *sis = SeqEntry::New (0x0008, 0x2112);
SQItem *sqi = SQItem::New(1);
- // (we assume 'SOP Instance UID' exists too)
- // create 'Referenced SOP Class UID'
-// DataEntry *e_0008_1150 = DataEntry::New(
-// Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
+
+ // 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();
- // create 'Referenced SOP Instance UID'
+ // create 'Referenced SOP Instance UID' from 'SOP Instance UID'
DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018);
-// DataEntry *e_0008_1155 = DataEntry::New(
-// Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
- DataEntry *e_0008_1155 = DataEntry::New(0x0008, 0x1155, "UI");
+
+ 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
}
}
- std::string pixelSpacing = FileInternal->GetEntryString(0x0028,0x0030);
- if ( pixelSpacing == GDCM_UNFOUND )
+ std::string pixelAspectRatio = FileInternal->GetEntryString(0x0028,0x0034);
+ if ( pixelAspectRatio == GDCM_UNFOUND ) // avoid conflict with pixelSpacing !
{
- pixelSpacing = "1.0\\1.0";
- // if missing, Pixel Spacing forced to "1.0\1.0"
- CopyMandatoryEntry(0x0028,0x0030,pixelSpacing,"DS");
- }
-
- // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
- // --> This one is the *legal* one !
- if ( ContentType != USER_OWN_IMAGE)
- // we write it only when we are *sure* the image comes from
- // an imager (see also 0008,0x0064)
- CheckMandatoryEntry(0x0018,0x1164,pixelSpacing,"DS");
-
+ std::string pixelSpacing = FileInternal->GetEntryString(0x0028,0x0030);
+ if ( pixelSpacing == GDCM_UNFOUND )
+ {
+ pixelSpacing = "1.0\\1.0";
+ // if missing, Pixel Spacing forced to "1.0\1.0"
+ CopyMandatoryEntry(0x0028,0x0030,pixelSpacing,"DS");
+ }
+
+ // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
+ // --> This one is the *legal* one !
+ if ( ContentType != USER_OWN_IMAGE)
+ // 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