-D__STDC_LIMIT_MACROS # Refer to stdint.h
libgdcm_la_LIBADD = \
+ $(top_builddir)/src/jpeg/libijg12/libgdcmijpeg12.la \
$(top_builddir)/src/jpeg/libijg8/libgdcmijpeg8.la
+
libgdcm_la_SOURCES= \
gdcmException.cxx \
gdcmUtil.cxx \
gdcmDictSet.cxx \
gdcmElValSet.cxx \
gdcmHeaderIdo.cxx \
- gdcmFile.cxx \
- gdcmVR.cxx \
- gdcmTS.cxx \
- gdcmJpeg.cxx \
+ gdcmFile.cxx \
+ gdcmVR.cxx \
+ gdcmTS.cxx \
+ gdcmJpeg.cxx \
+ gdcmJpeg12.cxx \
+ gdcmJpeg2000.cxx \
+ gdcmRLE.cxx \
gdcmJpegIdo.cxx
libgdcmincludedir = $(includedir)
}
tagHt.clear();
// Since Add() adds symetrical in both tagHt and NameHt we can
- // assume all the pointed gdcmElValues are allready cleaned-up when
+ // assume all the pointed gdcmElValues are already cleaned-up when
// we cleaned tagHt.
NameHt.clear();
}
NameHt[newElValue->GetName()] = newElValue;
}
-
/**
* \ingroup gdcmElValSet
* \brief Checks if a given Dicom element exists
e = tag->second->GetElement();
v = tag->second->GetValue();
o = tag->second->GetOffset();
- d = _CreateCleanString(v); // TODO : trouver qq chose moins goret
+ d = _CreateCleanString(v); // replace non printable characters by '.'
d2=d;
os << tag->first << ": ";
- //os << "[" << v << "]";
- os << "[" << d2 << "]";
- os << "[" << tag->second->GetName() << "]";
- os << "[" << tag->second->GetVR() << "]";
-
- if ( (g == 0x0002) && (e == 0x0010) ) {
- os << " [" << ts->GetValue(v) << "]";
- }
-
- // liberer 'd' ici ?
-
os << " lgr : " << tag->second->GetLength();
os << ", Offset : " << o;
os << " x(" << hex << o << dec << ") ";
+ os << "\t[" << tag->second->GetVR() << "]";
+ os << "\t[" << tag->second->GetName() << "]";
+ os << "\t[" << d2 << "]";
+
+ // Display the UID value (instead of displaying the rough code)
+ if (g == 0x0002) { // Some more to be displayed ?
+ if ( (e == 0x0010) || (e == 0x0002) )
+ os << " ==>\t[" << ts->GetValue(v) << "]";
+ } else {
+ if (g == 0x0008) {
+ if ( (e == 0x0016) || (e == 0x1150) )
+ os << " ==>\t[" << ts->GetValue(v) << "]";
+ }
+ }
+ free(d);
os << endl;
}
}
/**
* \ingroup gdcmElValSet
* \brief
- * @param length
+ * @param area
* @param group
* @param element
* @return
*/
+int gdcmElValSet::SetVoidAreaByNumber(void * area,
+ guint16 group, guint16 element) {
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHt.count(key))
+ return 0;
+ tagHt[key]->SetVoidArea(area);
+ return 1 ;
+}
+
+/**
+ * \ingroup gdcmElValSet
+ * \brief
+ * @param length
+ * @param group
+ * @param element
+ * @return int acts as a boolean
+ */
int gdcmElValSet::SetElValueLengthByNumber(guint32 length,
guint16 group, guint16 element) {
TagKey key = gdcmDictEntry::TranslateToKey(group, element);
tagHt[key]->SetLength(length);
return 1 ;
}
-
-
/**
* \ingroup gdcmElValSet
* \brief
/**
* \ingroup gdcmElValSet
* \brief Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
- * @param SkipSequence
+ * @param SkipSequence TRUE if we don't want to write Sequences (ACR-NEMA Files)
* @param type
*/
void gdcmElValSet::UpdateGroupLength(bool SkipSequence, FileType type) {
if (SkipSequence && vr == "SQ") continue;
+ // Still unsolved problem :
+ // we cannot find the 'Sequence Delimitation Item'
+ // since it's at the end of the Hash Table
+ // (fffe,e0dd)
+
// pas SEQUENCE en ACR-NEMA
- // WARNING : pb CERTAIN
- // si on est descendu 'a l'interieur' des SQ
- //
+ // WARNING :
// --> la descente a l'interieur' des SQ
- // devra etre faite avec une liste chainee, pas avec une HTable...
-
+ // devrait etre faite avec une liste chainee, pas avec une HTable...
+
if ( groupHt.count(key) == 0) { // we just read the first elem of a given group
if (el == 0x0000) { // the first elem is 0x0000
groupHt[key] = 0; // initialize group length
groupHt[key] += 2 + 2 + 4 + elem->GetLength();
}
}
+
unsigned short int gr_bid;
for (GroupHT::iterator g = groupHt.begin(); // for each group we found
* \ingroup gdcmElValSet
* \brief
* @param type
- * @param _fp
+ * @param _fp
* @return
*/
void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
lgr = tag2->second->GetLength();
val = tag2->second->GetValue().c_str();
vr = tag2->second->GetVR();
+
+ // cout << "Tag "<< hex << gr << " " << el << "\n";
if ( type == ACR ) {
- if (gr < 0x0008) continue;
- // if (gr %2) continue; // pour voir
- if (vr == "SQ" ) continue;
+ if (gr < 0x0008) continue; // ignore pure DICOM V3 groups
+ if (gr %2) continue; // ignore shadow groups
+ if (vr == "SQ" ) continue; // ignore Sequences
+ if (gr == 0xfffe ) continue; // ignore delimiters
}
fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element
if ( (type == ExplicitVR) && (gr <= 0x0002) ) {
- // On est en EXPLICIT VR
+ // EXPLICIT VR
guint16 z=0, shortLgr;
fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
shortLgr=lgr;
fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
}
- } else {
+ } else { // IMPLICIT VR
fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
}
- tokens.erase(tokens.begin(),tokens.end());
- Tokenize (tag2->second->GetValue(), tokens, "\\");
-
if (vr == "US" || vr == "SS") {
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (tag2->second->GetValue(), tokens, "\\");
for (unsigned int i=0; i<tokens.size();i++) {
val_uint16 = atoi(tokens[i].c_str());
ptr = &val_uint16;
fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
}
+ tokens.clear();
continue;
}
if (vr == "UL" || vr == "SL") {
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (tag2->second->GetValue(), tokens, "\\");
for (unsigned int i=0; i<tokens.size();i++) {
val_uint32 = atoi(tokens[i].c_str());
ptr = &val_uint32;
fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
}
+ tokens.clear();
continue;
- }
- tokens.clear();
-
- // Les pixels ne sont pas chargés dans l'element !
+ }
+ // Pixels are never loaded in the element !
if ((gr == 0x7fe0) && (el == 0x0010) ) break;
- fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
+ fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
}
}
-// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.15 2003/06/26 13:07:01 jpr Exp $
+// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.16 2003/07/23 08:43:03 jpr Exp $
#ifndef GDCMELVALSET_H
#define GDCMELVALSET_H
int SetElValueLengthByNumber(guint32 l, guint16 group, guint16 element);
int SetElValueLengthByName (guint32 l, std::string TagName);
+
+ int SetVoidAreaByNumber(void *a, guint16 Group, guint16 Elem );
guint32 GenerateFreeTagKeyInGroup(guint16 group);
int CheckIfExistByNumber(guint16 Group, guint16 Elem );
-// $Header: /cvs/public/gdcm/src/Attic/gdcmElValue.h,v 1.6 2003/06/17 17:44:48 jpr Exp $
+// $Header: /cvs/public/gdcm/src/Attic/gdcmElValue.h,v 1.7 2003/07/23 08:43:03 jpr Exp $
#ifndef GDCMELVALUE_H
#define GDCMELVALUE_H
friend class gdcmHeader;
public:
std::string value;
+ void * voidArea; // unsecure memory area to hold 'non string' values
+ // (ie : Lookup Tables, overlays)
size_t Offset; // Offset from the begining of file for direct user access
gdcmElValue(gdcmDictEntry*);
gdcmDictEntry * GetDictEntry(void) { return entry; };
- guint16 GetGroup(void) { return entry->GetGroup(); };
- guint16 GetElement(void) { return entry->GetElement();};
- std::string GetKey(void) { return entry->GetKey(); };
- std::string GetName(void) { return entry->GetName(); };
- std::string GetVR(void) { return entry->GetVR(); };
- std::string GetValue(void) { return value; };
- size_t GetOffset(void) { return Offset; };
- guint32 GetLength(void) { return LgrElem; };
+ guint16 GetGroup(void) { return entry->GetGroup(); };
+ guint16 GetElement(void) { return entry->GetElement();};
+ std::string GetKey(void) { return entry->GetKey(); };
+ std::string GetName(void) { return entry->GetName(); };
+ std::string GetVR(void) { return entry->GetVR(); };
+ std::string GetValue(void) { return value; };
+ void * GetVoidArea(void) { return voidArea; };
+ size_t GetOffset(void) { return Offset; };
+ guint32 GetLength(void) { return LgrElem; };
void SetVR(std::string v) { entry->SetVR(v); };
void SetLength(guint32 l) { LgrElem = l; };
- void SetValue(std::string val){ value = val; };
+ void SetValue(std::string val){ value = val; };
+ void SetVoidArea(void * area) { voidArea = area; };
};
#include "gdcmFile.h"
#include "gdcmUtil.h"
-#include "iddcmjpeg.h"
+#include "iddcmjpeg.h" // for the 'LibIDO' Jpeg LossLess
using namespace std;
+#define str2num(str, typeNum) *((typeNum *)(str))
+
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
nb = atoi(str_nb.c_str() );
if (nb == 12) nb =16;
}
- lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8)* GetSamplesPerPixel();;
+ lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8)* GetSamplesPerPixel();
+
+ string str_PhotometricInterpretation = gdcmHeader::GetPubElValByNumber(0x0028,0x0004);
+ if ( str_PhotometricInterpretation == "PALETTE COLOR "
+ || str_PhotometricInterpretation == "YBR_FULL") { // --> some more to be added !!
+ lgrTotale*=3;
+ }
+
+ // remaining to check :
+ // str_PhotometricInterpretation == "YBR_FULL"
+ // str_PhotometricInterpretation == "YBR_FULL_422" (no LUT, no Palette)
+ // -->and some more !!
}
/////////////////////////////////////////////////////////////////
}
+/////////////////////////////////////////////////////////////////
+/**
+ * \ingroup gdcmFile
+ * \brief Parse pixel data from disk and *prints* the result
+ * \ For multi-fragment Jpeg files checking purpose *only*
+ * \ Allows to 'see' if the file *does* conform
+ * \ (some of them do not)
+ * \ with Dicom Part 3, Annex A (PS 3.5-2003, page 58)
+ *
+ */
+bool gdcmFile::ParsePixelData(void) {
+ if ( !OpenFile())
+ return false;
+
+ if ( fseek(fp, GetPixelOffset(), SEEK_SET) == -1 ) {
+ CloseFile();
+ return false;
+ }
+
+ if ( !IsDicomV3() ||
+ IsImplicitVRLittleEndianTransferSyntax() ||
+ IsExplicitVRLittleEndianTransferSyntax() ||
+ IsExplicitVRBigEndianTransferSyntax() ||
+ IsDeflatedExplicitVRLittleEndianTransferSyntax() ) {
+
+ printf ("gdcmFile::ParsePixelData : non JPEG File\n");
+ return 0;
+ }
+
+ int nb;
+ string str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
+ if (str_nb == "gdcm::Unfound" ) {
+ nb = 16;
+ } else {
+ nb = atoi(str_nb.c_str() );
+ if (nb == 12) nb =16;
+ }
+ int nBytes= nb/8;
+
+ //int taille = GetXSize() * GetYSize() * GetZSize() * GetSamplesPerPixel();
+ int taille = GetXSize() * GetYSize() * GetSamplesPerPixel();
+
+ printf ("Checking the Dicom-Jpeg/RLE Pixels\n");
+
+ // ------------------------------- for Parsing : Position on begining of Jpeg Pixels
+ guint16 ItemTagGr,ItemTagEl;
+ int ln;
+ long ftellRes;
+ char * destination = NULL;
+ ftellRes=ftell(fp);
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Basic Offset Table Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Basic Offset Table Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
+ }
+ printf ("at %x : ItemTag (should be fffe,e000): %04x,%04x\n",
+ ftellRes,ItemTagGr,ItemTagEl );
+ ftellRes=ftell(fp);
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln); // Basic Offset Table Item Lentgh
+ printf("at %x : Basic Offset Table Item Lentgh (??) %d x(%08x)\n",
+ ftellRes,ln,ln);
+ if (ln != 0) {
+ // What is it used for ??
+ char * BasicOffsetTableItemValue= (char *)malloc(ln+1);
+ fread(BasicOffsetTableItemValue,ln,1,fp);
+ guint32 a;
+ for (int i=0;i<ln;i+=4){
+ a=str2num(&BasicOffsetTableItemValue[i],guint32);
+ printf(" x(%08x) %d\n",a,a);
+ }
+ }
+
+ ftellRes=ftell(fp);
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
+ }
+ printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+ ftellRes,ItemTagGr,ItemTagEl );
+
+ while ( ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { // Parse fragments
+
+ ftellRes=ftell(fp);
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln); // length
+ printf(" at %x : fragment length %d x(%08x)\n",
+ ftellRes, ln,ln);
+
+ destination += taille * nBytes; // location in user's memory
+
+ printf (" Destination will be x(%x) = %d \n",
+ destination,destination );
+
+ fseek(fp,ln,SEEK_CUR); // skipping (not reading) fragment pixels
+
+ ftellRes=ftell(fp);
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
+ }
+ printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+ ftellRes,ItemTagGr,ItemTagEl );
+
+
+ }
+ return 1;
+}
+
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
*
*/
bool gdcmFile::ReadPixelData(void* destination) {
+
if ( !OpenFile())
return false;
CloseFile();
return false;
}
+
+// ------------------------------- Uncompressed File
if ( !IsDicomV3() ||
IsImplicitVRLittleEndianTransferSyntax() ||
return true;
}
}
-
- // ------------------------------- Position on begining of Jpeg Pixels
-
- int ln;
- fseek(fp,4,SEEK_CUR);
- fread(&ln,4,1,fp);
- if(GetSwapCode())
- ln=SwapLong(ln);
- fseek(fp,ln,SEEK_CUR);
- fseek(fp,4,SEEK_CUR);
- fread(&ln,4,1,fp);
- if(GetSwapCode())
- ln=SwapLong(ln);
-
- // ------------------------------- JPEG LossLess : call to Jpeg Libido
-
- if (IsJPEGLossless()) {
-
- ClbJpeg* jpg = _IdDcmJpegRead(fp);
- if(jpg == NULL) {
- CloseFile();
- return false;
- }
-
+
+ // ----------------------------- JPEG Compressed File .
+
int nb;
string str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
if (str_nb == "gdcm::Unfound" ) {
if (nb == 12) nb =16;
}
int nBytes= nb/8;
- int * dataJpg = jpg->DataImg;
- int taille = GetXSize() * GetYSize() * GetZSize() * GetSamplesPerPixel();
+
+ //int taille = GetXSize() * GetYSize() * GetZSize() * GetSamplesPerPixel();
+ int taille = GetXSize() * GetYSize() * GetSamplesPerPixel();
+
+ // ------------------------------- JPEG LossLess : call to Jpeg Libido
+
+ if (IsJPEGLossless() && GetZSize() == 1) {
+
+ int ln; // Position on begining of Jpeg Pixels
+ fseek(fp,4,SEEK_CUR); // skipping (fffe,e000) : Basic Offset Table Item
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln); // Item length
+ fseek(fp,ln,SEEK_CUR); // skipping Basic Offset Table ('ln' bytes)
+ fseek(fp,4,SEEK_CUR); // skipping (fffe,e000) : First fragment Item Tag
+ fread(&ln,4,1,fp); // First fragment length (just to know)
+ if(GetSwapCode())
+ ln=SwapLong(ln);
+
+ ClbJpeg* jpg = _IdDcmJpegRead(fp); // TODO : find a 'full' one.
+ // (We use the LibIDO one :-(
+ if(jpg == NULL) {
+ CloseFile();
+ return false;
+ }
+ int * dataJpg = jpg->DataImg;
+
switch (nBytes) {
case 1:
{
unsigned short *dest = (unsigned short *)destination;
for (int i=0; i<taille; i++) {
- *((unsigned char *)dest+i) = *(dataJpg +i);
+ *((unsigned char *)dest+i) = *(dataJpg +i);
}
}
break;
*((unsigned short *)dest+i) = *(dataJpg +i);
}
}
- break;
-
- case 4:
- {
- unsigned int *dest=(unsigned int *)destination;
- for (int i=0;i<taille; i++) {
- *((unsigned int *)dest+i) = *(dataJpg +i);
- }
- }
- break;
+ break;
}
-
_IdDcmJpegFree (jpg);
return true;
}
// ------------------------------- JPEG Lossy : call to IJG 6b
-
- // TODO : faire qq chose d'intelligent pour limiter
- // la duplication du code JPEG <bits=8 / bits=12>
- // TODO : eplucher icelui pour traiter *egalement* bits=16
-
- int nBS;
- if ((nBS = GetBitsStored()) != 12) {
- printf("Sorry, Bits Stored = %d not yet taken into account\n",nBS);
- return false;
+
+ long fragmentBegining; // for ftell, fseek
+
+ bool a=0, b=0;
+
+ a = gdcmHeader::IsRLELossLessTransferSyntax();
+ if (!a)
+ bool b = gdcmHeader::IsJPEG2000();
+
+ bool res;
+ guint16 ItemTagGr,ItemTagEl;
+ int ln; // Position on begining of Jpeg Pixels
+
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
}
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln); // Basic Offset Table Item length
+
+ if (ln != 0) {
+ // What is it used for ?!?
+ char *BasicOffsetTableItemValue = (char *)malloc(ln+1);
+ fread(BasicOffsetTableItemValue,ln,1,fp);
+ }
+
+ // first Fragment initialisation
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
+ }
+
+ // parsing fragments until Sequence Delim. Tag found
+ //unsigned short *dest = (unsigned short *)destination;
+
+ while ( ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) {
+ fread(&ln,4,1,fp);
+ if(GetSwapCode())
+ ln=SwapLong(ln); // Fragment Item length
- bool res = (bool)gdcm_read_JPEG_file (destination);
+ // FIXME : multi fragments
+ fragmentBegining=ftell(fp);
+
+ if (a)
+ res = (bool)gdcm_read_RLE_file (destination); // Reading Fragment pixels
+ else if (b)
+ res = (bool)gdcm_read_JPEG2000_file (destination); // Reading Fragment pixels
+
+ else if (IsJPEGLossless()) { // ------------- call to LibIDO Jpeg for each Frame/fragment
+
+ // Warning : Works only if there is one fragment per frame
+ // (Or a single fragment for the multiframe file)
+ ClbJpeg* jpg = _IdDcmJpegRead(fp); // TODO : find a 'full' one.
+ // (We use the LibIDO one :-(
+ if(jpg == NULL) {
+ CloseFile();
+ return false;
+ }
+ int * dataJpg = jpg->DataImg;
+ unsigned short *dest = (unsigned short *)destination;
+ switch (nBytes) {
+ case 1:
+ {
+ for (int i=0; i<taille; i++) {
+ *((unsigned char *)dest+i) = *(dataJpg +i);
+ }
+ break;
+ }
+
+ case 2:
+ {
+ for (int i=0; i<taille; i++) {
+ *((unsigned short *)dest+i) = *(dataJpg +i);
+ }
+ break;
+ }
+ }
+ _IdDcmJpegFree (jpg);
+
+ } // ------------------------------------- endif (IsJPEGLossless())
+
+ else
+ if (GetBitsStored() == 8) {
+ res = (bool)gdcm_read_JPEG_file (destination); // Reading Fragment pixels
+ } else {
+ res = (bool)gdcm_read_JPEG_file12 (destination);// Reading Fragment pixels
+ }
+
+ if (!res) break;
+
+ // FIXME : will work only when each fragment corresponds to a Frame :-(
+
+ (char *) destination += taille * nBytes; // location in user's memory
+ // for next fragment (if any)
+ // TODO : find a suitable file (multifragment/single Frame Jpeg file) to check
+
+ fseek(fp,fragmentBegining,SEEK_SET); // To be sure we start
+ fseek(fp,ln,SEEK_CUR); // at the begining of next fragment
+
+ ItemTagGr = ItemTagEl =0;
+ fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
+ fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
+ if(GetSwapCode()) {
+ ItemTagGr=SwapShort(ItemTagGr);
+ ItemTagEl=SwapShort(ItemTagEl);
+ }
+
+ //(char *) destination += taille * nBytes;
+ //cout << "destination" << destination << "\n";
+ }
+
return res;
}
* \ingroup gdcmFile
* \brief Allocates necessary memory, copies the pixel data
* (image[s]/volume[s]) to newly allocated zone.
- * @return Pointer to newly allocated pixel data.
+ * @return Pointer to newly allocated pixel data.
+ * \ NULL if alloc fails
*/
void * gdcmFile::GetImageData (void) {
PixelData = (void *) malloc(lgrTotale);
- GetImageDataIntoVector(PixelData, lgrTotale);
+ if (PixelData)
+ GetImageDataIntoVector(PixelData, lgrTotale);
return(PixelData);
}
return (size_t)0;
}
- (void)ReadPixelData(destination);
+ (void)ReadPixelData(destination);
// Nombre de Bits Alloues pour le stockage d'un Pixel
- str_nb = GetPubElValByNumber(0x0028,0x0100);
- if (str_nb == "gdcm::Unfound" ) {
- nb = 16;
- } else {
- nb = atoi(str_nb.c_str() );
- }
+ str_nb = GetPubElValByNumber(0x0028,0x0100);
+ if (str_nb == "gdcm::Unfound" ) {
+ nb = 16;
+ } else {
+ nb = atoi(str_nb.c_str() );
+ }
// Nombre de Bits Utilises
- str_nbu=GetPubElValByNumber(0x0028,0x0101);
- if (str_nbu == "gdcm::Unfound" ) {
- nbu = nb;
- } else {
- nbu = atoi(str_nbu.c_str() );
- }
+ str_nbu=GetPubElValByNumber(0x0028,0x0101);
+ if (str_nbu == "gdcm::Unfound" ) {
+ nbu = nb;
+ } else {
+ nbu = atoi(str_nbu.c_str() );
+ }
// Position du Bit de Poids Fort
- str_highBit=GetPubElValByNumber(0x0028,0x0102);
- if (str_highBit == "gdcm::Unfound" ) {
- highBit = nb - 1;
- } else {
- highBit = atoi(str_highBit.c_str() );
- }
+ str_highBit=GetPubElValByNumber(0x0028,0x0102);
+ if (str_highBit == "gdcm::Unfound" ) {
+ highBit = nb - 1;
+ } else {
+ highBit = atoi(str_highBit.c_str() );
+ }
// Signe des Pixels
- str_signe=GetPubElValByNumber(0x0028,0x0103);
- if (str_signe == "gdcm::Unfound" ) {
- signe = 1;
- } else {
- signe = atoi(str_signe.c_str() );
- }
-
- // On remet les Octets dans le bon ordre si besoin est
+ str_signe=GetPubElValByNumber(0x0028,0x0103);
+ if (str_signe == "gdcm::Unfound" ) {
+ signe = 1;
+ } else {
+ signe = atoi(str_signe.c_str() );
+ }
+
+ // re arange bytes inside the integer
if (nb != 8)
SwapZone(destination, GetSwapCode(), lgrTotale, nb);
- // On remet les Bits des Octets dans le bon ordre si besoin est
+ // re arange bits inside the bytes
if (nbu != nb){
int l = (int)lgrTotale / (nb/8);
if (nb == 16) {
dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: wierd image");
return (size_t)0;
}
- }
+ }
- // ---
- string str_PlanarConfiguration = GetPubElValByNumber(0x0028,0x0006);
- int PlanarConfiguration;
- if (str_PlanarConfiguration == "gdcm::Unfound" ) {
- PlanarConfiguration = 0;
- } else {
- PlanarConfiguration = atoi(str_PlanarConfiguration.c_str() );
- }
- // ---
-
- // TODO : replace by
- // if (GetPlanarConfiguration() == 1) {
- // after unfreeze
+ // Try to deal with the color
+ // --------------------------
+
+ string str_PhotometricInterpretation = gdcmHeader::GetPubElValByNumber(0x0028,0x0004);
+
+ if ( (str_PhotometricInterpretation == "MONOCHROME1 ")
+ || (str_PhotometricInterpretation == "MONOCHROME2 ")
+ || (str_PhotometricInterpretation == "RGB")) {
+ return lgrTotale;
+ }
+
+ switch ( GetPlanarConfiguration() ) {
+ case 0:
+ // Pixels are already RGB
+ break;
- if (PlanarConfiguration == 1) { // need to make RGB Pixels
- int l = lgrTotale/3 ;
-
- char * a = (char *)destination;
- char * b = a + l;
- char * c = b + l;
- char * newDest = (char*) malloc(lgrTotale);
- // TODO :
- // any trick not to have to allocate temporary buffer is welcome ...
- char *x = newDest;
- for (int j=0;j<l; j++) {
- *(x++) = *(a++);
- *(x++) = *(b++);
- *(x++) = *(c++);
+ case 1:
+ // need to make RGB Pixels from Planes R,G,B
+ {
+ int l = lgrTotale/3 ;
+
+ char * a = (char *)destination;
+ char * b = a + l;
+ char * c = b + l;
+ char * newDest = (char*) malloc(lgrTotale);
+ // TODO :
+ // any trick not to have to allocate temporary buffer is welcome ...
+ char *x = newDest;
+ for (int j=0;j<l; j++) {
+ *(x++) = *(a++);
+ *(x++) = *(b++);
+ *(x++) = *(c++);
+ }
+ memmove(destination,newDest,lgrTotale);
+ free(newDest);
+ // now, it's an RGB image
+ string spp = "3";
+ gdcmHeader::SetPubElValByNumber(spp,0x0028,0x0002);
+ string rgb="RGB";
+ gdcmHeader::SetPubElValByNumber(rgb,0x0028,0x0004);
+ break;
}
- a = (char *)destination;
- x = newDest;
- for (int i=0;i<lgrTotale; i++) {
- *(a++) = *(x++);
+
+ case 2:
+ // from Lut R + Lut G + Lut B
+
+ // we no longer use gdcmHeader::GetLUTRGB
+ // since a lot of images have wrong info
+ // in the Lookup Table Descriptors (0028,1101),...
+ {
+ unsigned char *lutR =(unsigned char *)GetPubElValVoidAreaByNumber(0x0028,0x1201);
+ unsigned char *lutG =(unsigned char *)GetPubElValVoidAreaByNumber(0x0028,0x1202);
+ unsigned char *lutB =(unsigned char *)GetPubElValVoidAreaByNumber(0x0028,0x1203);
+
+ if (lutR && lutG && lutB ) { // need to make RGB Pixels
+ // from grey Pixels
+ // and Lut R,Lut G,Lut B
+ unsigned char * newDest = (unsigned char*) malloc(lgrTotale);
+ int l = lgrTotale/3;
+ memmove(newDest, destination, l);// move Gray pixels to temp area
+
+ unsigned char * x = newDest;
+ unsigned char * a = (unsigned char *)destination;
+ int j;
+ for (int i=0;i<l; i++) {
+ j=newDest[i]*2; // Who can explain *why* we have to skip bytes
+ *a++ = lutR[j];
+ *a++ = lutG[j];
+ *a++ = lutB[j];
+ }
+ free(newDest);
+
+ // now, it's an RGB image
+ string spp = "3";
+ gdcmHeader::SetPubElValByNumber(spp,0x0028,0x0002);
+ string rgb="RGB";
+ gdcmHeader::SetPubElValByNumber(rgb,0x0028,0x0004);
+
+ } else { // need to make RGB Pixels (?)
+ // from grey Pixels (?!)
+ // and Gray Lut (!?!)
+ unsigned char *lutGray =(unsigned char *)GetPubElValVoidAreaByNumber(0x0028,0x1200);
+ // Well . I'll wait till I find such an image
+ }
+ break;
}
- free(newDest);
- }
+ }
+
return lgrTotale;
}
-
//
// Je laisse le code integral, au cas ça puisse etre reutilise ailleurs
//
+/**
+ * \ingroup gdcmFile
+ * \brief Swap the bytes, according to swap code.
+ * \warning not end user intended
+ * @param im area to deal with
+ * @param swap swap code
+ * @param lgr Area Length
+ * @param nb Pixels Bit number
+ */
+
void gdcmFile::SwapZone(void* im, int swap, int lgr, int nb) {
guint32 s32;
guint16 fort,faible;
break;
default:
- printf("valeur de SWAP (16 bits) non autorisee : %d\n", swap);
+ printf("valeur de SWAP (16 bits) not allowed : %d\n", swap);
}
if( nb == 32 )
break;
default:
- printf("valeur de SWAP (32 bits) non autorisee : %d\n", swap);
+ printf(" SWAP value (32 bits) not allowed : %d\n", swap);
}
return;
}
/**
* \ingroup gdcmFile
* \brief TODO JPR
- * \warning doit-etre etre publique ? FIXME JPR
+ * \warning doit-etre etre publique ?
* TODO : y a-t-il un inconvenient à fusioner ces 2 fonctions
*
- * @param inData TODO JPR
- * @param ExpectedSize TODO JPR
+ * @param inData
+ * @param ExpectedSize
*
- * @return TODO JPR
+ * @return integer acts as a boolean
*/
int gdcmFile::SetImageData(void * inData, size_t ExpectedSize) {
SetImageDataSize(ExpectedSize);
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- * \brief TODO JPR
- * \
- * \warning WARNING doit-etre etre publique ? FIXME JPR
+ * \brief Sets the Pixel Area size in the Header
+ * --> not-for-rats function
+ *
+ * \warning WARNING doit-etre etre publique ?
* TODO : y aurait il un inconvenient à fusionner ces 2 fonctions
*
- * @param ImageDataSize TODO JPR
- *
+ * @param ImageDataSize new Pixel Area Size
+ * warning : nothing else is checked
*/
void gdcmFile::SetImageDataSize(size_t ImageDataSize) {
-
string content1;
- char car[20];
-
- // suppose que le ElValue (0x7fe0, 0x0010) existe ...
-
+ char car[20];
+ // Assumes ElValue (0x7fe0, 0x0010) exists ...
sprintf(car,"%d",ImageDataSize);
gdcmElValue*a = GetElValueByNumber(0x7fe0, 0x0010);
* \brief Ecrit sur disque les pixels d'UNE image
* Aucun test n'est fait sur l'"Endiannerie" du processeur.
* Ca sera à l'utilisateur d'appeler son Reader correctement
- * (Equivalent a IdImaWriteRawFile) FIXME JPR
- *
- * @param nomFichier TODO JPR
+ * (Equivalent a IdImaWriteRawFile)
*
- * @return TODO JPR
+ * @param fileName
+ * @return
*/
-int gdcmFile::WriteRawData (string nomFichier) {
-
+int gdcmFile::WriteRawData (string fileName) {
FILE * fp1;
- fp1 = fopen(nomFichier.c_str(),"wb");
+ fp1 = fopen(fileName.c_str(),"wb");
if (fp1 == NULL) {
- printf("Echec ouverture (ecriture) Fichier [%s] \n",nomFichier.c_str());
+ printf("Echec ouverture (ecriture) Fichier [%s] \n",fileName.c_str());
return (0);
- }
-
+ }
fwrite (PixelData,lgrTotale, 1, fp1);
fclose (fp1);
return(1);
}
-
-
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \brief Ecrit sur disque UNE image Dicom
* Aucun test n'est fait sur l'"Endiannerie" du processeur.
* Ca fonctionnera correctement (?) sur processeur Intel
- * (Equivalent a IdDcmWrite) FIXME JPR
- *
- * @param nomFichier TODO JPR
+ * (Equivalent a IdDcmWrite)
*
- * @return TODO JPR
+ * @param fileName
+ * @return int acts as a boolean
*/
-int gdcmFile::WriteDcmImplVR (string nomFichier) {
- return WriteBase(nomFichier, ImplicitVR);
+int gdcmFile::WriteDcmImplVR (string fileName) {
+ return WriteBase(fileName, ImplicitVR);
}
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- *
- * @param nomFichier TODO JPR
- *
- * @return TODO JPR
+ * \brief
+ * @param fileName
+ * @return int acts as a boolean
*/
-int gdcmFile::WriteDcmImplVR (const char* nomFichier) {
- return WriteDcmImplVR (string (nomFichier));
+int gdcmFile::WriteDcmImplVR (const char* fileName) {
+ return WriteDcmImplVR (string (fileName));
}
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- *
- * @param nomFichier TODO JPR
- *
- * @return TODO JPR
+ * \brief
+ * @param fileName
+ * @return int acts as a boolean
*/
-int gdcmFile::WriteDcmExplVR (string nomFichier) {
- return WriteBase(nomFichier, ExplicitVR);
+int gdcmFile::WriteDcmExplVR (string fileName) {
+ return WriteBase(fileName, ExplicitVR);
}
/////////////////////////////////////////////////////////////////
* Ca fonctionnera correctement (?) sur processeur Intel
* (Equivalent a IdDcmWrite)
*
- * @param nomFichier TODO JPR
- *
- * @return TODO JPR
+ * @param fileName
+ * @return int acts as a boolean
*/
-int gdcmFile::WriteAcr (string nomFichier) {
- return WriteBase(nomFichier, ACR);
+int gdcmFile::WriteAcr (string fileName) {
+ return WriteBase(fileName, ACR);
}
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
*
- * @param FileName TODO JPR
- * @param type TODO JPR
+ * @param FileName
+ * @param type
*
- * @return TODO JPR
+ * @return int acts as a boolean
*/
int gdcmFile::WriteBase (string FileName, FileType type) {
if ( (type == ImplicitVR) || (type == ExplicitVR) ) {
char * filePreamble;
- // Ecriture Dicom File Preamble
+ // writing Dicom File Preamble
filePreamble=(char*)calloc(128,1);
fwrite(filePreamble,128,1,fp1);
fwrite("DICM",4,1,fp1);
int Parsed; // weather already parsed
std::string OrigFileName; // To avoid file overwrite
void SwapZone(void* im, int swap, int lgr, int nb);
+
bool ReadPixelData(void * destination);
- int gdcm_read_JPEG_file (void * image_buffer);
+ int gdcm_read_JPEG_file (void * image_buffer); // For JPEG 8 Bits
+ int gdcm_read_JPEG_file12 (void * image_buffer); // For JPEG 12 Bits
+ int gdcm_read_JPEG2000_file (void * image_buffer); // For JPEG 2000 (TODO)
+ int gdcm_read_RLE_file (void * image_buffer); // For Run Length Encoding (TODO)
+
protected:
int WriteBase(std::string FileName, FileType type);
// Aucun test n'est fait sur l'"Endiannerie" du processeur.
// Ca sera à l'utilisateur d'appeler son Reader correctement
- int WriteRawData (std::string nomFichier);
- int WriteDcmImplVR(std::string nomFichier);
- int WriteDcmImplVR(const char * nomFichier);
- int WriteDcmExplVR(std::string nomFichier);
- int WriteAcr (std::string nomFichier);
+ int WriteRawData (std::string fileName);
+ int WriteDcmImplVR(std::string fileName);
+ int WriteDcmImplVR(const char * fileName);
+ int WriteDcmExplVR(std::string fileName);
+ int WriteAcr (std::string fileName);
+
+ bool ParsePixelData(void);
};
#endif
-// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.78 2003/07/03 14:38:16 jpr Exp $
+// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.79 2003/07/23 08:43:03 jpr Exp $
#include <stdio.h>
#include <cerrno>
#include "gdcmUtil.h"
#include "gdcmHeader.h"
using namespace std;
+#include "gdcmTS.h"
// TODO : remove DEBUG
// Refer to gdcmHeader::CheckSwap()
#define HEADER_LENGTH_TO_READ 256
// Refer to gdcmHeader::SetMaxSizeLoadElementValue()
-#define _MaxSizeLoadElementValue_ 1024
-
+//#define _MaxSizeLoadElementValue_ 1024
+#define _MaxSizeLoadElementValue_ 4096
/**
* \ingroup gdcmHeader
* \brief
/**
* \ingroup gdcmHeader
* \brief
- * @return
+ * @return TRUE if the close was successfull
*/
bool gdcmHeader::CloseFile(void) {
int closed = fclose(fp);
// CRV Curve
// OLY Overlays
// PXL Pixels
+// DL Delimiters
//
/**
// 0x00000004. Finding the swap code in then straigthforward. Trouble
// occurs when we can't find such group...
guint32 s;
- guint32 x=4; // x : pour ntohs
+ guint32 x=4; // x : for ntohs
bool net2host; // true when HostByteOrder is the same as NetworkByteOrder
int lgrLue;
return false;
}
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was already encountered
+ * and if it corresponds to a RLE Lossless one.
+ *
+ * @return True when RLE Lossless found. False in all
+ * other cases.
+ */
+bool gdcmHeader::IsRLELossLessTransferSyntax(void) {
+ gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( Transfer == "1.2.840.10008.1.2.5" )
+ return true;
+ return false;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Determines if the Transfer Syntax was already encountered
+ * and if it corresponds to a JPEG200 one.0
+ *
+ * @return True when JPEG2000 (Lossly or LossLess) found. False in all
+ * other cases.
+ */
+bool gdcmHeader::IsJPEG2000(void) {
+ gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return false;
+ LoadElementValueSafe(Element);
+ string Transfer = Element->GetValue();
+ if ( (Transfer == "1.2.840.10008.1.2.4.90")
+ || (Transfer == "1.2.840.10008.1.2.4.91") )
+ return true;
+ return false;
+}
+
/**
* \ingroup gdcmHeader
* \brief Predicate for dicom version 3 file.
/**
* \ingroup gdcmHeader
* \brief
- *
+ * @param ElVal
* @return
*/
void gdcmHeader::SkipElementValue(gdcmElValue * ElVal) {
/**
* \ingroup gdcmHeader
* \brief
- *
+ * @param NewSize
* @return
*/
void gdcmHeader::SetMaxSizeLoadElementValue(long NewSize) {
// Heuristic : a sequence "contains" a set of tags (called items). It looks
// like the last tag of a sequence (the one that terminates the sequence)
// has a group of 0xfffe (with a dummy length).
+ // Well ...
+ // Actually (fffe e000) tells us an Element is beginning
+ // (fffe e00d) tells us an Element just ended
+ // (fffe e0dd) tells us the current SEQuence just ended
+
if( group == 0xfffe )
SkipLoad = true;
/**
* \ingroup gdcmHeader
- * \brief
+ * \brief Reads a supposed to be 16 Bits integer
+ * \ (swaps it depending on processor endianity)
*
- * @return
+ * @return integer acts as a boolean
*/
guint16 gdcmHeader::ReadInt16(void) {
guint16 g;
/**
* \ingroup gdcmHeader
- * \brief
+ * \brief Reads a supposed to be 32 Bits integer
+ * \ (swaps it depending on processor endianity)
*
* @return
*/
* @param Value
* @param Group
* @param Elem
+ * \return integer acts as a boolean
*/
int gdcmHeader::ReplaceOrCreateByNumber(string Value, guint16 Group, guint16 Elem ) {
/**
* \ingroup gdcmHeader
- * \brief TODO
- * @param Value
+ * \brief Modify or (Creates if not found) an element
+ * @param Value new value
* @param Group
- * @param Elem
+ * @param Elem
+ * \return integer acts as a boolean
+ *
*/
int gdcmHeader::ReplaceOrCreateByNumber(char* Value, guint16 Group, guint16 Elem ) {
return(1);
}
+
/**
* \ingroup gdcmHeader
- * \brief TODO
+ * \brief Set a new value if the invoked element exists
+ * @param Value
+ * @param Group
+ * @param Elem
+ * \return integer acts as a boolean
+ */
+int gdcmHeader::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) {
+
+ gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem);
+ string v = Value;
+ PubElValSet.SetElValueByNumber(v, Group, Elem);
+ return 1;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief Checks if a given ElValue (group,number)
+ * \ exists in the Public ElValSet
* @param Group
- * @param Elem
+ * @param Elem
+ * @return integer acts as a boolean
*/
int gdcmHeader::CheckIfExistByNumber(guint16 Group, guint16 Elem ) {
return (PubElValSet.CheckIfExistByNumber(Group, Elem));
}
-
-
+
/**
* \ingroup gdcmHeader
* \brief Build a new Element Value from all the low level arguments.
for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) {
LoadElementValue(tag->second);
}
+ // Load 'non string' values
+ rewind(fp);
+ 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
+ }
}
/**
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) {
+ cout << "Big Broblem (LoadElementVoidArea, malloc) "
+ << hex << Group << " " << Elem << "\n";
+ return NULL;
+ }
+ int res = PubElValSet.SetVoidAreaByNumber(a, Group, Elem);
+ // TODO check the result
+ size_t l2 = fread(a, 1, l ,fp);
+ if(l != l2) {
+ cout << "Big Broblem (LoadElementVoidArea, fread) "
+ << hex << Group << " " << Elem << "\n";
+ free(a);
+ return NULL;
+ }
+}
+
+/**
+ * \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();
+}
+
+
//
// =============================================================================
-// Accesors with euristics
+// Heuristics based accessors
//==============================================================================
//
return atoi(StrSize.c_str());
}
-
-/* ================ COMMENT OUT after unfreeze
-**
+/**
* \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) {
string StrSize = GetPubElValByNumber(0x0028,0x0006);
if (StrSize == "gdcm::Unfound")
return atoi(StrSize.c_str());
}
- ======================================= */
-
/**
* \ingroup gdcmHeader
* \brief Return the size (in bytes) of a single pixel of data.
}
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0002,0010 : Transfert Syntax
+ * \ else 1.
+ * @return Transfert Syntax Name (as oposite to Transfert Syntax UID)
+ */
+string gdcmHeader::GetTransferSyntaxName(void) {
+ string TransfertSyntax = GetPubElValByNumber(0x0002,0x0010);
+ if (TransfertSyntax == "gdcm::Unfound") {
+ dbg.Verbose(0, "gdcmHeader::GetTransferSyntaxName: unfound Transfert Syntax (0002,0010)");
+ return "Uncompressed ACR-NEMA";
+ }
+ // we do it only when we need it
+ gdcmTS * ts = gdcmGlobal::GetTS();
+ string tsName=ts->GetValue(TransfertSyntax);
+ //delete ts; // Seg Fault when deleted ?!
+ return tsName;
+}
+
+// -------------------------------- Lookup Table related functions ------------
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0028,1101 : Lookup Table Desc-Red
+ * \ else 0
+ * @return Lookup Table Length
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ */
+
+int gdcmHeader::GetLUTLength(void) {
+ vector<string> tokens;
+ int LutLength;
+ //int LutDepth;
+ //int LutNbits;
+ // Just hope Lookup Table Desc-Red = Lookup Table Desc-Red = Lookup Table Desc-Blue
+ string LutDescriptionR = GetPubElValByNumber(0x0028,0x1101);
+ if (LutDescriptionR == "gdcm::Unfound")
+ return 0;
+ string LutDescriptionG = GetPubElValByNumber(0x0028,0x1102);
+ if (LutDescriptionG == "gdcm::Unfound")
+ return 0;
+ string LutDescriptionB = GetPubElValByNumber(0x0028,0x1103);
+ if (LutDescriptionB == "gdcm::Unfound")
+ return 0;
+ if( (LutDescriptionR != LutDescriptionG) || (LutDescriptionR != LutDescriptionB) ) {
+ dbg.Verbose(0, "gdcmHeader::GetLUTLength: The CLUT R,G,B are not equal");
+ return 0;
+ }
+ cout << "Lut Description " << LutDescriptionR <<"\n";
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (LutDescriptionR, tokens, "\\");
+ LutLength=atoi(tokens[0].c_str());
+ //LutDepth=atoi(tokens[1].c_str());
+ //LutNbits=atoi(tokens[2].c_str());
+ tokens.clear();
+ return LutLength;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0028,1101 : Lookup Table Desc-Red
+ * \ else 0
+ * @return Lookup Table nBit
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ */
+
+int gdcmHeader::GetLUTNbits(void) {
+ vector<string> tokens;
+ //int LutLength;
+ //int LutDepth;
+ int LutNbits;
+ // Just hope Lookup Table Desc-Red = Lookup Table Desc-Red = Lookup Table Desc-Blue
+ // Consistency already checked in GetLUTLength
+ string LutDescription = GetPubElValByNumber(0x0028,0x1101);
+ if (LutDescription == "gdcm::Unfound")
+ return 0;
+ tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+ Tokenize (LutDescription, tokens, "\\");
+ //LutLength=atoi(tokens[0].c_str());
+ //LutDepth=atoi(tokens[1].c_str());
+ LutNbits=atoi(tokens[2].c_str());
+ tokens.clear();
+ return LutNbits;
+}
+
+
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0028,1201 : Lookup Table Red
+ * \ else 0
+ * @return Lookup Table Red
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ */
+void * gdcmHeader::GetLUTRed(void) {
+ return GetPubElValVoidAreaByNumber(0x0028,0x1201);
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0028,1202 : Lookup Table Green
+ * \ else 0
+ * @return Lookup Table Red
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ */
+ void * gdcmHeader::GetLUTGreen(void) {
+ return GetPubElValVoidAreaByNumber(0x0028,0x1202);
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief gets the info from 0028,1202 : Lookup Table Blue
+ * \ else 0
+ * @return Lookup Table Blue
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ */
+void * gdcmHeader::GetLUTBlue(void) {
+ return GetPubElValVoidAreaByNumber(0x0028,0x1203);
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief
+ * @return Lookup Table RGB
+ * \ when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+ * \ and (0028,1201),(0028,1202),(0028,1202) are found
+ * \warning : hazardous ! Use better GetPubElValVoidAreaByNumber
+ */
+void * gdcmHeader::GetLUTRGB(void) {
+// Not so easy : see
+// http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
+// and OT-PAL-8-face.dcm
+
+ if (GetPubElValByNumber(0x0028,0x0004) == "gdcm::Unfound") {
+ dbg.Verbose(0, "gdcmHeader::GetLUTRGB: unfound Photometric Interpretation");
+ return NULL;
+ }
+ void * LutR,*LutG,*LutB;
+ int l;
+
+ // Maybe, some day we get an image
+ // that respects the definition ...
+ // Let's consider no ones does.
+
+ l= GetLUTLength();
+ if(l==0)
+ return (NULL);
+ int nBits=GetLUTNbits();
+ // a virer quand on aura trouve UNE image
+ // qui correspond VRAIMENT à la definition !
+ cout << "l " << l << " nBits " << nBits;
+
+ l= l/(nBits/8);
+
+ LutR =GetPubElValVoidAreaByNumber(0x0028,0x1201);
+ LutG =GetPubElValVoidAreaByNumber(0x0028,0x1202);
+ LutB =GetPubElValVoidAreaByNumber(0x0028,0x1203);
+
+ // Warning : Any value for nBits as to be considered as 8
+ // Any value for Length as to be considered as 256
+ // That's DICOM ...
+
+ // Just wait before removing the following code
+ /*
+ if (nBits == 16) {
+ guint16 * LUTRGB, *rgb;
+ LUTRGB = rgb = (guint16 *) malloc(3*l*sizeof( guint16));
+ guint16 * r = (guint16 *)LutR;
+ guint16 * g = (guint16 *)LutG;
+ guint16 * b = (guint16 *)LutB;
+ for(int i=0;i<l;i++) {
+ *rgb++ = *r++;
+ *rgb++ = *g++;
+ *rgb++ = *b++;
+ }
+ return(LUTRGB);
+ } else
+
+ */ { // we assume it's always 8 Bits
+ l=256; // we assume ...
+ unsigned char * LUTRGB, *rgb;
+ LUTRGB = rgb = (unsigned char *) malloc(3*l*sizeof( char));
+ unsigned char * r = (unsigned char *)LutR;
+ unsigned char * g = (unsigned char *)LutG;
+ unsigned char * b = (unsigned char *)LutB;
+ for(int i=0;i<l;i++) {
+ //cout << "lut16 " << i << " : " << *r << " " << *g << " " << *b << "\n";
+ printf("lut 8 %d : %d %d %d \n",i,*r,*g,*b);
+ *rgb++ = *r++;
+ *rgb++ = *g++;
+ *rgb++ = *b++;
+ }
+ free(LutR); free(LutB); free(LutG);
+ return(LUTRGB);
+ }
+}
+
-// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.h,v 1.34 2003/07/07 10:26:14 regrain Exp $
+// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.h,v 1.35 2003/07/23 08:43:03 jpr Exp $
#ifndef GDCMHEADER_H
#define GDCMHEADER_H
bool IsJPEGExtendedProcess2_4TransferSyntax(void);
bool IsJPEGExtendedProcess3_5TransferSyntax(void);
bool IsJPEGSpectralSelectionProcess6_8TransferSyntax(void);
+ bool IsRLELossLessTransferSyntax(void);
bool IsJPEGLossless(void);
+ bool IsJPEG2000(void);
bool IsDicomV3(void);
virtual void ParseHeader(bool exception_on_error = false)
std::string GetPubElValRepByName (std::string TagName);
std::string GetPubElValByNumber (guint16 group, guint16 element);
std::string GetPubElValRepByNumber(guint16 group, guint16 element);
-
+
+ size_t GetPubElValOffsetByNumber(guint16 Group, guint16 Elem);
+ void * GetPubElValVoidAreaByNumber(guint16 Group, guint16 Elem);
+ void * LoadElementVoidArea(guint16 Group, guint16 Element);
+
TagElValueHT & GetPubElVal(void) { return PubElValSet.GetTagHt(); };
void PrintPubElVal(std::ostream & os = std::cout);
void PrintPubDict (std::ostream & os = std::cout);
int ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem);
int ReplaceOrCreateByNumber( char * Value, guint16 Group, guint16 Elem);
-
+ int ReplaceIfExistByNumber ( char * Value, guint16 Group, guint16 Elem);
+
+ int Write(FILE *, FileType);
+
+ // Some heuristic based accessors, end user intended
+
int GetXSize(void);
int GetYSize(void);
int GetZSize(void);
int GetBitsStored(void);
int GetSamplesPerPixel(void);
-/* ================ COMMENT OUT after unfreeze
int GetPlanarConfiguration(void);
- ======================================= */
int GetPixelSize(void);
std::string GetPixelType(void);
float GetYImagePosition(void);
float GetZImagePosition(void);
- int Write(FILE *, FileType);
+ string GetTransferSyntaxName(void);
+ int GetLUTLength(void);
+ int GetLUTNbits(void);
+ void * GetLUTRed(void);
+ void * GetLUTGreen(void);
+ void * GetLUTBlue(void);
+ void * GetLUTRGB(void);
+
+
};
#endif
#include <stdio.h>
#include "gdcmFile.h"
+// for jpeglib defined BITS_IN_JSAMPLE
+#include "jpeg/libijg8/jBitsInJsample.h"
+// FIXME : find something else when both
+// libJpeg8 and libJpeg12 will be active
+
#define DEBUG 0
+/*
+DICOM provides a mechanism for supporting the use of JPEG Image Compression
+through the Encapsulated Format (see PS 3.3 of the DICOM Standard).
+Annex A defines a number of Transfer Syntaxes which reference
+the JPEG Standard and provide a number of lossless (bit preserving)
+and lossy compression schemes.
+In order to facilitate interoperability of implementations conforming
+to the DICOM Standard which elect to use one or more
+of the Transfer Syntaxes for JPEG Image Compression, the following policy is specified:
+
+ Any implementation which conforms to the DICOM Standard and has elected
+ to support any one of the Transfer Syntaxes for lossless JPEG Image Compression,
+ shall support the following lossless compression:
+ The subset (first-order horizontal prediction [Selection Value 1) of JPEG Process 14
+ (DPCM, non-hierarchical with Huffman coding) (see Annex F of the DICOM Standard).
+
+ Any implementation which conforms to the DICOM Standard and has elected
+ to support any one of the Transfer Syntaxes for 8-bit lossy JPEG Image Compression,
+ shall support the JPEG Baseline Compression (coding Process 1).
+
+ Any implementation which conforms to the DICOM Standard and has elected
+ to support any one of the Transfer Syntaxes for 12-bit lossy JPEG Image Compression,
+ shall support the JPEG Compression Process 4.
+
+Note: The DICOM conformance statement shall differentiate between implementations
+that can simply receive JPEG encoded images and those that can receive and process
+JPEG encoded images (see PS 3.2 of the DICOM Standard).
+
+The use of the DICOM Encapsulated Format to support JPEG Compressed Pixel Data
+implies that the Data Elements which are related to the Native Format Pixel Data encoding
+(e.g. Bits Allocated, Bits Stored, High Bit, Pixel Representation, Rows, Columns, etc.)
+shall contain values which are consistent with the characteristics
+of the uncompressed pixel data from which the compressed Data Stream was derived.
+The Pixel Data characteristics included in the JPEG Interchange Format
+shall be used to decode the compressed data stream.
+
+Run Length Encoding Compression
+
+DICOM provides a mechanism for supporting the use of Run Length Encoding (RLE)
+Compression which is a byte oriented lossless compression scheme through
+the encapsulated Format (see PS 3.3 of this Standard).
+Annex G of the DICOM Standard defines RLE Compression and its Transfer Syntax.
+
+Note: The RLE Compression algorithm described in Annex G
+of the DICOM Standard is the compression used in
+the TIFF 6.0 specification known as the "PackBits" scheme.
+
+The use of the DICOM Encapsulated Format to support RLE Compressed Pixel Data
+implies that the Data Elements which are related to the Native Format Pixel Data encoding (
+e.g. Bits Allocated, Bits Stored, High Bit, Pixel Representation, Rows, Columns, etc.)
+shall contain values which are consistent with the characteristics
+of the uncompressed pixel data from which the compressed data is derived
+*/
+
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
* the second part of the example.
JSAMPARRAY buffer; /* Output row buffer */
// rappel :
+ // ------
// typedef unsigned char JSAMPLE;
// typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
// typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
+
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
//(void) jpeg_read_scanlines(&cinfo, pimage, 1);
- (void) jpeg_read_scanlines(&cinfo, buffer, 1);
- memcpy( pimage, buffer[0],row_stride*2 ); // FIXME : *2 car 16 bits?!?
-
- pimage+=row_stride*2; // FIXME : *2 car 16 bits?!?
+ (void) jpeg_read_scanlines(&cinfo, buffer, 1);
+
+ if ( BITS_IN_JSAMPLE == 8) {
+ memcpy( pimage, buffer[0],row_stride);
+ pimage+=row_stride;
+ } else {
+ memcpy( pimage, buffer[0],row_stride*2 ); // FIXME : *2 car 16 bits?!?
+ pimage+=row_stride*2; // FIXME : *2 car 16 bits?!?
+ }
}
/* Step 7: Finish decompression */
*/
+
+
+
+
+
-SUBDIRS = libijg8
+SUBDIRS = libijg12 \
+ libijg8