+ rewind(fp);
+
+ // We don't use any longer the HashTable, since a lot a stuff is missing
+ // when SeQuences were encountered
+ //
+ //TagElValueHT ht = PubElValSet.GetTagHt();
+ //for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
+ // LoadElementValue(tag->second);
+ //}
+
+ for (ListTag::iterator i = GetListElem().begin();
+ i != GetListElem().end();
+ ++i){
+ LoadElementValue(*i);
+ }
+
+ rewind(fp);
+
+ // Load 'non string' values
+ std::string PhotometricInterpretation = GetPubElValByNumber(0x0028,0x0004);
+ if( PhotometricInterpretation == "PALETTE COLOR " ){
+ LoadElementVoidArea(0x0028,0x1200); // gray LUT
+ LoadElementVoidArea(0x0028,0x1201); // R LUT
+ LoadElementVoidArea(0x0028,0x1202); // G LUT
+ LoadElementVoidArea(0x0028,0x1203); // B LUT
+
+ LoadElementVoidArea(0x0028,0x1221); // Segmented Red Palette Color LUT Data
+ LoadElementVoidArea(0x0028,0x1222); // Segmented Green Palette Color LUT Data
+ LoadElementVoidArea(0x0028,0x1223); // Segmented Blue Palette Color LUT Data
+ }
+
+ // --------------------------------------------------------------
+ // Special Patch to allow gdcm to read ACR-LibIDO formated images
+ //
+ // if recognition code tells us we deal with a LibIDO image
+ // we switch lineNumber and columnNumber
+ //
+ std::string RecCode;
+ RecCode = GetPubElValByNumber(0x0008, 0x0010);
+ if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
+ RecCode == "CANRME_AILIBOD1_1." ) {
+ filetype = ACR_LIBIDO;
+ std::string rows = GetPubElValByNumber(0x0028, 0x0010);
+ std::string columns = GetPubElValByNumber(0x0028, 0x0011);
+ SetPubElValByNumber(columns, 0x0028, 0x0010);
+ SetPubElValByNumber(rows , 0x0028, 0x0011);
+ }
+ // ----------------- End of Special Patch ----------------
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief
+ * @return
+ */
+void gdcmHeader::PrintPubElVal(std::ostream & os) {
+ PubElValSet.Print(os);
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief
+ * @return
+ */
+void gdcmHeader::PrintPubDict(std::ostream & os) {
+ RefPubDict->Print(os);
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief
+ * @return integer, acts as a Boolean
+ */
+int 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
+
+ PubElValSet.SetElValueLengthByNumber(18, 0x0002, 0x0010);
+ }
+
+ if (type == ExplicitVR) {
+ std::string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
+ ReplaceOrCreateByNumber(explicitVRTransfertSyntax,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
+
+ PubElValSet.SetElValueLengthByNumber(20, 0x0002, 0x0010);
+ }
+
+ return PubElValSet.Write(fp, type);
+}
+
+//
+// ------------------------ 'non string' elements related functions
+//
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Loads (from disk) the element content
+ * when a string is not suitable
+ */
+void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) {
+ gdcmElValue * Element= PubElValSet.GetElementByNumber(Group, Elem);
+ if ( !Element )
+ return NULL;
+ size_t o =(size_t)Element->GetOffset();
+ fseek(fp, o, SEEK_SET);
+ int l=Element->GetLength();
+ void * a = malloc(l);
+ if(!a) {
+ return NULL;
+ }
+ /* int res = */ PubElValSet.SetVoidAreaByNumber(a, Group, Elem);
+ // TODO check the result
+ size_t l2 = fread(a, 1, l ,fp);
+ if(l != l2) {
+ free(a);
+ return NULL;
+ }
+ return a;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Gets (from Header) the offset of a 'non string' element value
+ * \ (LoadElementValue has already be executed)
+ * @param Group
+ * @param Elem
+ * @return File Offset of the Element Value
+ */
+ size_t gdcmHeader::GetPubElValOffsetByNumber(guint16 Group, guint16 Elem) {
+ gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem);
+ if (!elValue) {
+ dbg.Verbose(1, "gdcmHeader::GetElValueByNumber",
+ "failed to Locate gdcmElValue");
+ return (size_t)0;
+ }
+ return elValue->GetOffset();
+}
+
+/**
+ * \ingroup gdcmHeader
+* \brief Gets (from Header) a 'non string' element value
+ * \ (LoadElementValue has already be executed)
+ * @param Group
+ * @param Elem
+ * @return Pointer to the 'non string' area
+
+ */
+ void * gdcmHeader::GetPubElValVoidAreaByNumber(guint16 Group, guint16 Elem) {
+ gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem);
+ if (!elValue) {
+ dbg.Verbose(1, "gdcmHeader::GetElValueByNumber",
+ "failed to Locate gdcmElValue");
+ return (NULL);
+ }
+ return elValue->GetVoidArea();
+}
+
+
+//
+// =============================================================================
+// Heuristics based accessors
+//==============================================================================
+//
+
+// TODO : move to an other file.
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of columns of image.
+ * @return The encountered size when found, 0 by default.
+ */
+int gdcmHeader::GetXSize(void) {
+ // We cannot check for "Columns" because the "Columns" tag is present
+ // both in IMG (0028,0011) and OLY (6000,0011) sections of the dictionary.
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0011);
+ if (StrSize == GDCM_UNFOUND)
+ return 0;
+ return atoi(StrSize.c_str());
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of lines of image.
+ * \warning The defaulted value is 1 as opposed to gdcmHeader::GetXSize()
+ * @return The encountered size when found, 1 by default.
+ */
+int gdcmHeader::GetYSize(void) {
+ // We cannot check for "Rows" because the "Rows" tag is present
+ // both in IMG (0028,0010) and OLY (6000,0010) sections of the dictionary.
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0010);
+ if (StrSize != GDCM_UNFOUND)
+ return atoi(StrSize.c_str());
+ if ( IsDicomV3() )
+ return 0;
+ else
+ // The Rows (0028,0010) entry is optional for ACR/NEMA. It might
+ // hence be a signal (1d image). So we default to 1:
+ return 1;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of planes of volume or the number
+ * of frames of a multiframe.
+ * \warning When present we consider the "Number of Frames" as the third
+ * dimension. When absent we consider the third dimension as
+ * being the "Planes" tag content.
+ * @return The encountered size when found, 1 by default.
+ */
+int gdcmHeader::GetZSize(void) {
+ // Both in DicomV3 and ACR/Nema the consider the "Number of Frames"
+ // as the third dimension.
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0008);
+ if (StrSize != GDCM_UNFOUND)
+ return atoi(StrSize.c_str());
+
+ // We then consider the "Planes" entry as the third dimension [we
+ // cannot retrieve by name since "Planes tag is present both in
+ // IMG (0028,0012) and OLY (6000,0012) sections of the dictionary].
+ StrSize = GetPubElValByNumber(0x0028,0x0012);
+ if (StrSize != GDCM_UNFOUND)
+ return atoi(StrSize.c_str());
+ return 1;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of Bits Stored
+ * (as opposite to number of Bits Allocated)
+ *
+ * @return The encountered number of Bits Stored, 0 by default.
+ */
+int gdcmHeader::GetBitsStored(void) {
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0101);
+ if (StrSize == GDCM_UNFOUND)
+ return 1;
+ return atoi(StrSize.c_str());
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of Bits Allocated
+ * (8, 12 -compacted ACR-NEMA files, 16, ...)
+ *
+ * @return The encountered number of Bits Allocated, 0 by default.
+ */
+int gdcmHeader::GetBitsAllocated(void) {
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0100);
+ if (StrSize == GDCM_UNFOUND)
+ return 1;
+ return atoi(StrSize.c_str());
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the number of Samples Per Pixel
+ * (1 : gray level, 3 : RGB -1 or 3 Planes-)
+ *
+ * @return The encountered number of Samples Per Pixel, 1 by default.
+ */
+int gdcmHeader::GetSamplesPerPixel(void) {
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0002);
+ if (StrSize == GDCM_UNFOUND)
+ return 1; // Well, it's supposed to be mandatory ...
+ return atoi(StrSize.c_str());
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Retrieve the Planar Configuration for RGB images
+ * (0 : RGB Pixels , 1 : R Plane + G Plane + B Plane)
+ *
+ * @return The encountered Planar Configuration, 0 by default.
+ */
+int gdcmHeader::GetPlanarConfiguration(void) {
+ std::string StrSize = GetPubElValByNumber(0x0028,0x0006);
+ if (StrSize == GDCM_UNFOUND)
+ return 0;
+ return atoi(StrSize.c_str());
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Return the size (in bytes) of a single pixel of data.
+ * @return The size in bytes of a single pixel of data.
+ *
+ */
+int gdcmHeader::GetPixelSize(void) {
+ std::string PixelType = GetPixelType();
+ if (PixelType == "8U" || PixelType == "8S")
+ return 1;
+ if (PixelType == "16U" || PixelType == "16S")
+ return 2;
+ if (PixelType == "32U" || PixelType == "32S")
+ return 4;
+ dbg.Verbose(0, "gdcmHeader::GetPixelSize: Unknown pixel type");
+ return 0;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Build the Pixel Type of the image.
+ * Possible values are:
+ * - 8U unsigned 8 bit,
+ * - 8S signed 8 bit,
+ * - 16U unsigned 16 bit,
+ * - 16S signed 16 bit,
+ * - 32U unsigned 32 bit,
+ * - 32S signed 32 bit,
+ * \warning 12 bit images appear as 16 bit.
+ * \ 24 bit images appear as 8 bit
+ * @return
+ */
+std::string gdcmHeader::GetPixelType(void) {
+ std::string BitsAlloc;
+ BitsAlloc = GetElValByName("Bits Allocated");
+ if (BitsAlloc == GDCM_UNFOUND) {
+ dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
+ BitsAlloc = std::string("16");
+ }
+ if (BitsAlloc == "12") // It will be unpacked
+ BitsAlloc = std::string("16");
+ else if (BitsAlloc == "24") // (in order no to be messed up
+ BitsAlloc = std::string("8"); // by old RGB images)
+
+ std::string Signed;
+ Signed = GetElValByName("Pixel Representation");
+ if (Signed == GDCM_UNFOUND) {
+ dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Pixel Representation");
+ BitsAlloc = std::string("0");
+ }
+ if (Signed == "0")
+ Signed = std::string("U");
+ else
+ Signed = std::string("S");
+
+ return( BitsAlloc + Signed);