+2003-04-9 Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+ * src/Makefile.am now exports all the necessary include files at
+ make install stage.
+
2003-04-9 JPR
* UpdateGroupLength replaced by new one
2003-04-7 Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
* Data/im_00001 renamed to gdcm-MR-PHILIPS-16-Multi-Seq.dcm
+ * gdcmPython/testSuite.py now include a test of gdcmFile::Write.
* src:
- gdcmHeader::GetPubElValSet removed.
- gdcmElValSet::WriteDcm, WriteAcr, WriteExplVR, revamped to
UpdateGroupLength, WriteElements, Write.
+ - gdcmHeader::FileType moved to gdcmCommon.h. The enum FileType
+ doesn't contain TrueDicom anymore since ExplicitVR and ImplicitVR
+ carried the same semantics.
+ - src/gdcmHeaderIdo.cxx changed accordingly.
+ - gdcmFile::WriteBase now regroups all the codes from previous
+ versions of WriteDcm, WriteDcmImplVR, and WriteACR.
- enum FileType moved to gdcmCommon.h
+ * src/gdcmHeader.cxx AddDefault trashed
+ * gdcmGetXSize added
+ * getimageDataSize now calls gdcmGetXSize
* Test/*.cxx changed to agree with above changes
2003-03-31 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
-EXCLUDE =
+EXCLUDE = ../src/iddcmjpeg.h ../src/gdcmJpeg.cxx
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
# that are symbolic links (a Unix filesystem feature) are excluded from the input.
["Pixel Representation", "0"],
["Manufacturer", "FUJI PHOTO FILM CO. LTD."],
["Manufacturer Model Name", "9000"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:776 Length:387200"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:776 Length:387200"] ] ],
####################################
# CT modality examples:
####################################
["Pixel Representation", "1"],
["Manufacturer", "Picker International, Inc."],
["Manufacturer Model Name", "PQ5000"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1680 Length:524288"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1680 Length:524288"] ] ],
["CT-MONO2-16-ort.dcm",
[ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE
["Modality", "CT"],
["Pixel Representation", "1"],
["Manufacturer", "GE MEDICAL SYSTEMS"],
["Manufacturer Model Name", "HiSpeed CT/i"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1674 Length:524288"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1674 Length:524288"] ] ],
["CT-MONO2-16-ankle.dcm",
[ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little
["Modality", "CT"],
["Pixel Representation", "1"],
["Manufacturer", "GE MEDICAL SYSTEMS"],
["Manufacturer Model Name", "GENESIS_ZEUS"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1148 Length:524288"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1148 Length:524288"] ] ],
["CT-MONO2-8-abdo.dcm",
[ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little
["Modality", "CT"],
["High Bit", "7"],
["Pixel Representation", "0"],
["Manufacturer", "FUJI"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:796 Length:262144"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:796 Length:262144"] ] ],
["CT-MONO2-12-lomb-an2.acr2",
[ ["Modality", "CT"],
#"Transfer Syntax UID" and "Photometric Interpretation" are absent.
["High Bit", "11"],
["Pixel Representation", "0"],
["Manufacturer", "SIEMENS"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1230 Length:524288"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1230 Length:524288"] ] ],
["CT-MONO2-16-chest.dcm",
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg...
["Modality", "CT"],
["High Bit", "15"],
["Pixel Representation", "1"],
["Manufacturer", "GE MEDICAL SYSTEMS"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1638 Length:143498"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1638 Length:143498"] ] ],
####################################
### MR modality examples:
####################################
["Pixel Representation", "0"],
["Manufacturer", "Philips"],
# Note: 256*256*12/8 = 98304
- ["7fe0|0010", "gdcm::NotLoaded. Address:650 Length:98304"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:650 Length:98304"] ] ],
["MR-MONO2-12-an2.acr2",
[ ["Modality", "MR"],
["Photometric Interpretation", "MONOCHROME2"],
["Pixel Representation", "0"],
["Manufacturer", "SIEMENS"],
["Manufacturer Model Name", "MAGNETOM VISION"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1866 Length:131072"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1866 Length:131072"] ] ],
["MR-MONO2-16-head.dcm",
[ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Imp VR, LE
["Modality", "MR"],
["Pixel Representation", "1"],
["Manufacturer", "GE MEDICAL SYSTEMS"],
["Manufacturer Model Name", "GENESIS_SIGNA"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1804 Length:131072"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1804 Length:131072"] ] ],
# MR-MONO2-12-shoulder example is present in the Jpeg section.
# MR-MONO2-16-knee is not present in the test suite since it is too
# closely related to MR-MONO2-16-head.dcm to be of interest.
["Bits Allocated", "8"],
["High Bit", "7"],
["Pixel Representation", "0"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1654 Length:307200"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1654 Length:307200"] ] ],
# OT-MONO2-8-colon is not present in the test suite since it is too
# closely related to OT-MONO2-8-a7 to be of interest.
["OT-MONO2-8-a7.dcm",
["High Bit", "7"],
["Pixel Representation", "0"],
["Manufacturer", "Philips Medical Systems"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:438 Length:262144"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:438 Length:262144"] ] ],
####################################
# US (Ultra Sound) modality examples:
####################################
["Manufacturer", "Acme Products"],
# FIXME: 92160 / (120*256) = 3 bytes per pixel NOT 1. Maybe
# it has something to do with [Samples Per Pixel] = [3] ???
- ["7fe0|0010", "gdcm::NotLoaded. Address:904 Length:92160"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:904 Length:92160"] ] ],
["US-RGB-8-epicard.dcm",
# Interest: Big endian transfert syntax
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.2"], # Big endian
# FIXME: 921600/(480*640) = 3 bytes per pixel NOT 1. Maybe
# it has something to do with [Samples Per Pixel] = [3] ???
["Implementation Version Name", "OFFIS-DCMTK-311"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1012 Length:921600"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1012 Length:921600"] ] ],
]
MultiFrameFiles = [
["Pixel Representation", "0"],
["Manufacturer", "Philips"],
# Note: 256*256*16=1048576 (16 is the number of Frames)
- ["7fe0|0010", "gdcm::NotLoaded. Address:920 Length:1048576"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:920 Length:1048576"] ] ],
["NM-MONO2-16-13x-heart.dcm",
# Interest: NM modality, multi-frame
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE
["Pixel Representation", "0"],
["Manufacturer", "ACME Products"],
# Note: 64*64*13*2=106496
- ["7fe0|0010", "gdcm::NotLoaded. Address:1234 Length:106496"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1234 Length:106496"] ] ],
["US-MONO2-8-8x-execho.dcm",
# Interest: multi-frame
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE
["High Bit", "7"],
["Pixel Representation", "0"],
["Manufacturer", "Acme Products"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:976 Length:122880"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:976 Length:122880"] ] ],
["US-PAL-8-10x-echo.dcm",
# Interest: RLE (Run Length Encoded) compression, multiframe
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.5"], # RLE
["High Bit", "7"],
["Pixel Representation", "0"],
["Manufacturer", "ACME Products"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:2428 Length:481182"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:2428 Length:481182"] ] ],
["XA-MONO2-8-12x-catheter.dcm",
# Interest: XA modality, multi-frame
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg
["High Bit", "7"],
["Pixel Representation", "0"],
["Manufacturer", "Acme Products"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1006 Length:920072"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1006 Length:920072"] ] ],
]
GdcmFiles = [
["Manufacturer Model Name", "GBS III"],
# FIXME: this image looks padded at the end. The length of the file
# is 140288. Notice that, 256*256*2 + 1024 = 131072 + 1024 = 132096
- ["7fe0|0010", "gdcm::NotLoaded. Address:8192 Length:132096"],
+ ["Pixel Data", "gdcm::NotLoaded. Address:8192 Length:132096"],
# Oddities: "Study ID" and "Series Number" are empty
["Study ID", ""],
["Series Number", ""] ] ],
["Series Instance UID",
"1.3.12.2.1107.5.2.4.7630.20000918175714000007"],
["Series Number", "7"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:6052 Length:524288"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:6052 Length:524288"] ] ],
["gdcm-US-ALOKA-16.dcm",
# Interest: - possesses 3 LUTS: a Green (checked), a Red and BLue.
# - announced as implicit VR, but really explicit VR.
["Pixel Representation", "0"],
["Manufacturer", "ALOKA CO., LTD."],
["Manufacturer Model Name", "SSD-4000"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:258740 Length:614400"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:258740 Length:614400"] ] ],
["gdcm-MR-PHILIPS-16.dcm",
# Interest: - possesses a sequence
# - dicom file, with a recognition code of ACR-NEMA1
["Manufacturer", "Philips Medical Systems"],
["Manufacturer Model Name", "Gyroscan Intera"],
["Sequence Variant", "OTHER"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:6584 Length:131072"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:6584 Length:131072"] ] ],
["gdcm-MR-PHILIPS-16-Multi-Seq.dcm",
# Interest: - possesses many sequences in group 0x0029
# - Big sequence 28808 bytes at (0x0029, 0x263d)
["Manufacturer", "Philips Medical Systems"],
["Manufacturer Model Name", "Gyroscan Intera"],
["Sequence Variant", "OTHER"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:35846 Length:32768"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:35846 Length:32768"] ] ],
["gdcm-MR-PHILIPS-16-NonRectPix.dcm",
# Interest: - pixels are non rectangular
# - private elements are in explicit VR (which is normal)
["Manufacturer", "Philips Medical Systems"],
["Manufacturer Model Name", "Gyroscan Intera"],
["Pixel Spacing", "0.487416\\0.194966"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:5010 Length:20480"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:5010 Length:20480"] ] ],
["gdcm-CR-DCMTK-16-NonSamplePerPix.dcm",
# Interest: - Misses the "Samples Per Pixel" element which prevents
# e-film from reading it.
["High Bit", "7"],
["Pixel Representation", "0"],
["Implementation Version Name", "OFFIS_DCMTK_341"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:740 Length:562500"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:740 Length:562500"] ] ],
]
GdcmJpegFiles = [
["Pixel Representation", "0"],
["Manufacturer", "SIEMENS"],
["Manufacturer Model Name", "Volume Zoom"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:2946 Length:192218"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:2946 Length:192218"] ] ],
["MR-MONO2-12-shoulder.dcm",
# Interest: Jpeg compression [Lossless, non-hierar. (14)]
[ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.57"],
["Pixel Representation", "0"],
["Manufacturer", "Philips Medical Systems"],
["Manufacturer Model Name", "Gyroscan NT"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:1580 Length:718948"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:1580 Length:718948"] ] ],
["gdcm-JPEG-LossLess3a.dcm",
# Interest: - Jpeg compression [Lossless, hierar., first-order
# pred. 14, Select. Val. 1]
["Pixel Representation", "0"],
["Manufacturer", "Philips Medical Systems"],
["Manufacturer Model Name", "Cassette Holder Type 9840 500 35201"],
- ["7fe0|0010", "gdcm::NotLoaded. Address:3144 Length:4795668"] ] ],
+ ["Pixel Data", "gdcm::NotLoaded. Address:3144 Length:4795668"] ] ],
]
def _BaseTest(self, FileSet):
Source.GetImageData()
TargetFileName = "junk"
Target = Source.WriteDcmImplVR(TargetFileName)
- Sign = 'c7d6bedae1bef3851f35b29952fbbd4b'
+ Sign = '5af8739c15dd579dea223eb3930cacda'
ComputeSign = md5.new(open(TargetFileName).read()).hexdigest()
#print ComputeSign
self.assertEqual(ComputeSign, Sign,
libgdcminclude_HEADERS = \
gdcmException.h \
gdcmHeader.h \
- gdcmFile.h
-
-EXTRA_DIST = \
- gdcmUtil.h \
- gdcm.h \
- gdcmIdo.h \
gdcmCommon.h \
+ gdcm.h \
gdcmDictSet.h \
gdcmDict.h \
gdcmDictEntry.h \
gdcmElValue.h \
gdcmElValSet.h \
+ gdcmFile.h
+
+EXTRA_DIST = \
+ gdcmUtil.h \
+ gdcmIdo.h \
iddcmjpeg.h
* @param element element of the entry to be found
* @return the corresponding dictionnary entry when existing, NULL otherwise
*/
-gdcmDictEntry * gdcmDict::GetTagByKey(guint16 group, guint16 element) {
+gdcmDictEntry * gdcmDict::GetTagByNumber(guint16 group, guint16 element) {
TagKey key = gdcmDictEntry::TranslateToKey(group, element);
if ( ! KeyHt.count(key))
return (gdcmDictEntry*)0;
int ReplaceEntry(gdcmDictEntry* NewEntry);
int RemoveEntry (TagKey key);
int RemoveEntry (guint16 group, guint16 element);
- gdcmDictEntry * GetTagByKey(guint16 group, guint16 element);
+ gdcmDictEntry * GetTagByNumber(guint16 group, guint16 element);
gdcmDictEntry * GetTagByName(TagName name);
void Print(ostream&);
void PrintByKey(ostream&);
str_trash=trash;
elemZ->SetValue(str_trash);
}
-
- // Liberer groupHt !
-
}
void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
// gdcmFile.cxx
#include "gdcmFile.h"
-
-static void _Swap(void* im, int swap, int lgr, int nb);
+#include "gdcmUtil.h"
+#include "iddcmjpeg.h"
/////////////////////////////////////////////////////////////////
/**
gdcmFile::gdcmFile(string & filename)
:gdcmHeader(filename.c_str())
{
+ SetPixelDataSizeFromHeader();
}
gdcmFile::gdcmFile(const char * filename)
:gdcmHeader(filename)
{
+ SetPixelDataSizeFromHeader();
}
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- * \brief Renvoie la longueur A ALLOUER pour recevoir les pixels de l'image
+ * \brief calcule la longueur (in bytes) A ALLOUER pour recevoir les
+ * pixels de l'image
* ou DES images dans le cas d'un multiframe
* ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels
* (dans le cas d'images compressees, elle n'a pas de sens).
* @return longueur a allouer
*/
-size_t gdcmFile::GetImageDataSize(void) {
- int nb;
- string str_nb;
+void gdcmFile::SetPixelDataSizeFromHeader(void) {
+ int nb;
+ string str_nb;
- str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
- if (str_nb == "gdcm::Unfound" ) {
- nb = 16;
- } else {
- nb = atoi(str_nb.c_str() );
+ 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;
- }
+ }
+ lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8);
+}
- size_t lgrTotale = GetXSize() * GetYSize() * GetZSize() *(nb/8);
- return (lgrTotale);
+/**
+ * \ingroup gdcmFile
+ * \brief Accessor
+ */
+size_t gdcmFile::GetImageDataSize(void) {
+ return (lgrTotale);
}
+/**
+ * \ingroup gdcmFile
+ * \brief Read pixel data from disk (optionaly decompressing) into the
+ * caller specified memory location.
+ * @param destination Where the pixel data should be stored.
+ *
+ */
+bool gdcmFile::ReadPixelData(void* destination) {
+ if ( !OpenFile())
+ return false;
+ if ( fseek(fp, GetPixelOffset(), SEEK_SET) == -1 ) {
+ CloseFile();
+ return false;
+ }
+ if (IsJPEGLossless()) {
+ destination = _IdDcmJpegRead(fp);
+ } else {
+ size_t ItemRead = fread(destination, lgrTotale, 1, fp);
+ if ( ItemRead != 1 ) {
+ CloseFile();
+ return false;
+ }
+ }
+ CloseFile();
+ return true;
+}
/////////////////////////////////////////////////////////////////
/**
- * \ingroup gdcmFile
- * \brief TODO
- * \warning WARNING
- *
+ * \ingroup gdcmFile
+ * \brief Allocates necessary memory, copies the pixel data
+ * (image[s]/volume[s]) to newly allocated zone and return a
+ * pointer to it:
*/
void * gdcmFile::GetImageData (void) {
- char * _Pixels;
- // Longueur en Octets des Pixels a lire
- size_t taille = GetImageDataSize();// ne faudrait-il pas la stocker?
- _Pixels = (char *) malloc(taille);
- GetImageDataIntoVector(_Pixels, taille);
-
- // On l'affecte à un champ du dcmFile
- Pixels = _Pixels;
- lgrTotale = taille;
-
- // ca fait double emploi, il faudra nettoyer ça
-
- return(_Pixels);
+ PixelData = (void *) malloc(lgrTotale);
+ GetImageDataIntoVector(PixelData, lgrTotale);
+ return(PixelData);
}
-
-
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
* \brief amene en mémoire dans une zone précisee par l'utilisateur
- * les Pixels d'une image NON COMPRESSEE
- * \Warning Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image
+ * les Pixels d'une image
*
* @param destination
* @param MaxSize
*
- * @return TODO JPR
+ * @return The number of bytes actually copied.
*/
-int gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) {
-
-// Question :
-// dans quel cas la MaxSize sert-elle a quelque chose?
-// que fait-on si la taille de l'image est + gde que Maxize?
-// que fait-on si la taille de l'image est + petite que Maxize?
+size_t gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) {
+ int nb, nbu, highBit, signe;
+ string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
+
+ if ( lgrTotale > MaxSize ) {
+ dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: pixel data bigger"
+ "than caller's expected MaxSize");
+ return (size_t)0;
+ }
- void * Pixels = destination; // pour garder le code identique avec GetImageData
-
- int nb, nbu, highBit, signe;
- string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe;
-
- unsigned short int mask = 0xffff;
-
- // Longueur en Octets des Pixels a lire
- size_t _lgrTotale = GetImageDataSize(); // ne faudrait-il pas la stocker?
-
- // si lgrTotale < MaxSize ==> Gros pb
- // -> on résoud à la goret
-
- if ( _lgrTotale < MaxSize ) MaxSize = _lgrTotale;
-
- GetPixels(MaxSize, destination);
+ (void)ReadPixelData(destination);
- // Nombre de Bits Alloues pour le stockage d'un Pixel
- str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100);
-
+ // 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() );
}
- // Nombre de Bits Utilises
+ // Nombre de Bits Utilises
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
+ // Position du Bit de Poids Fort
str_highBit=GetPubElValByNumber(0x0028,0x0102);
-
if (str_highBit == "gdcm::Unfound" ) {
highBit = nb - 1;
} else {
// 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
- if (nb != 8) {
- int _sw = GetSwapCode();
-
- _Swap (destination, _sw, _lgrTotale, nb);
- }
-
- // On remet les Bits des Octets dans le bon ordre si besoin est
- //
- // ATTENTION : Jamais confronté a des pixels stockes sur 32 bits
- // avec moins de 32 bits utilises
- // et dont le bit de poids fort ne serait pas la ou on l'attend ...
- // --> ne marchera pas dans ce cas
- if (nbu!=nb){
- mask = mask >> (nb-nbu);
- int l=(int)MaxSize/(nb/8);
- unsigned short *deb = (unsigned short *)Pixels;
- for(int i=0;i<l;i++) {
- *deb = (*deb >> (nbu-highBit-1)) & mask;
- deb ++;
- }
- }
-
- // VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader
-
- return 1;
+ // On remet les Octets dans le bon ordre si besoin est
+ if (nb != 8)
+ SwapZone(destination, GetSwapCode(), lgrTotale, nb);
+
+ // On remet les Bits des Octets dans le bon ordre si besoin est
+ if (nbu != nb){
+ int l = (int)lgrTotale / (nb/8);
+ if (nb == 16) {
+ guint16 mask = 0xffff;
+ mask = mask >> (nb-nbu);
+ guint16 *deb = (guint16 *)destination;
+ for(int i = 0; i<l; i++) {
+ *deb = (*deb >> (nbu-highBit-1)) & mask;
+ deb ++;
+ }
+ } else if (nb == 32 ) {
+ guint32 mask = 0xffffffff;
+ mask = mask >> (nb-nbu);
+ guint32 *deb = (guint32 *)destination;
+ for(int i = 0; i<l; i++) {
+ *deb = (*deb >> (nbu-highBit-1)) & mask;
+ deb ++;
+ }
+ } else {
+ dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: wierd image");
+ return (size_t)0;
+ }
+ }
+ return lgrTotale;
}
// Je laisse le code integral, au cas ça puisse etre reutilise ailleurs
//
-static void _Swap(void* im, int swap, int lgr, int nb) {
+void gdcmFile::SwapZone(void* im, int swap, int lgr, int nb) {
guint32 s32;
guint16 fort,faible;
int i;
*
* @return TODO JPR
*/
-int gdcmFile::SetImageData(void * Data, size_t ExpectedSize) {
-
- SetImageDataSize(ExpectedSize);
-
- Pixels = Data;
- lgrTotale = ExpectedSize;
-
- return(1);
+int gdcmFile::SetImageData(void * inData, size_t ExpectedSize) {
+ SetImageDataSize(ExpectedSize);
+ PixelData = inData;
+ lgrTotale = ExpectedSize;
+ return(1);
}
return (0);
}
- fwrite (Pixels,lgrTotale, 1, fp1);
+ fwrite (PixelData,lgrTotale, 1, fp1);
fclose (fp1);
return(1);
}
/////////////////////////////////////////////////////////////////
/**
* \ingroup gdcmFile
- * \brief Ecrit sur disque UNE image ACR-NEMA
+ * \brief Ecrit au format ACR-NEMA sur disque l'entete et les pixels
* (a l'attention des logiciels cliniques
* qui ne prennent en entrée QUE des images ACR ...
- * si un header DICOM est fourni en entree,
+ * \warning si un header DICOM est fourni en entree,
* les groupes < 0x0008 et les groupes impairs sont ignores)
- * Aucun test n'est fait sur l'"Endiannerie" du processeur.
+ * \warning Aucun test n'est fait sur l'"Endiannerie" du processeur.
* Ca fonctionnera correctement (?) sur processeur Intel
* (Equivalent a IdDcmWrite)
*
}
gdcmHeader::Write(fp1, type);
- fwrite(Pixels, lgrTotale, 1, fp1);
+ fwrite(PixelData, lgrTotale, 1, fp1);
fclose (fp1);
return(1);
}
// In addition to Dicom header exploration, this class is designed
// for accessing the image/volume content. One can also use it to
// write Dicom files.
-////// QUESTION: this looks still like an open question whether the
-////// relationship between a gdcmFile and gdcmHeader is of
-////// type IS_A or HAS_A !
class GDCM_EXPORT gdcmFile: public gdcmHeader
{
private:
- // QUESTION :
- // Data pointe sur quoi?
- // sur les Pixels lus?
- // --> j'ajoute un champ public : Pixels
- // (il faudra que l'utilisateur puisse modifier les pixels ?)
-
- void* Data;
+ void* PixelData;
+ size_t lgrTotale;
int Parsed; // weather allready parsed
string OrigFileName; // To avoid file overwrite
+ void SwapZone(void* im, int swap, int lgr, int nb);
+ bool ReadPixelData(void * destination);
protected:
int WriteBase(string FileName, FileType type);
public:
- // je ne suis pas sur d'avoir compris *où* il serait légitime de ranger ca.
- // on pourra tjs le deplacer, et mettre des accesseurs
- void * Pixels;
- size_t lgrTotale;
-
- // Constructor dedicated to writing a new DICOMV3 part10 compliant
- // file (see SetFileName, SetDcmTag and Write)
- // TODO Swig gdcmFile();
- // Opens (in read only and when possible) an existing file and checks
- // for DICOM compliance. Returns NULL on failure.
- // Note: the in-memory representation of all available tags found in
- // the DICOM header is post-poned to first header information access.
- // This avoid a double parsing of public part of the header when
- // one sets an a posteriori shadow dictionary (efficiency can be
- // seen as a side effect).
-
gdcmFile(string & filename);
gdcmFile(const char * filename);
// from the constructor's one (no overwriting allowed).
// TODO Swig int SetFileName(string filename);
- // Allocates necessary memory, copies the data (image[s]/volume[s]) to
- // newly allocated zone and return a pointer to it:
-
- void * GetImageData();
-
+ void SetPixelDataSizeFromHeader(void);
// Returns size (in bytes) of required memory to contain data
// represented in this file.
-
size_t GetImageDataSize();
+ // Allocates necessary memory, copies the data (image[s]/volume[s]) to
+ // newly allocated zone and return a pointer to it:
+ void * GetImageData();
+
// Copies (at most MaxSize bytes) of data to caller's memory space.
// Returns an error code on failure (if MaxSize is not big enough)
-
- int GetImageDataIntoVector(void* destination, size_t MaxSize );
+ size_t GetImageDataIntoVector(void* destination, size_t MaxSize );
// Allocates ExpectedSize bytes of memory at this->Data and copies the
- // pointed data to it.
-
- // Question :
- // Pourquoi dupliquer les pixels, alors qu'on les a deja en mémoire,
- // et que Data (dans le gdcmHeader) est un pointeur ?
-
+ // pointed data to it. Copying the image might look useless but
+ // the caller might destroy it's image (without knowing it: think
+ // of a complicated interface where display is done with a library
+ // e.g. VTK) before calling the Write
int SetImageData (void * Data, size_t ExpectedSize);
+ // When the caller is aware we simply point to the data:
+ // TODO int SetImageDataNoCopy (void * Data, size_t ExpectedSize);
void SetImageDataSize (size_t ExpectedSize);
// Push to disk.
#include "gdcmUtil.h"
#include "gdcmHeader.h"
-#include "iddcmjpeg.h"
-
// Refer to gdcmHeader::CheckSwap()
#define HEADER_LENGTH_TO_READ 256
// Refer to gdcmHeader::SetMaxSizeLoadElementValue()
RefShaDict = (gdcmDict*)0;
}
-gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error)
- throw(gdcmFileError) {
+gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error) {
SetMaxSizeLoadElementValue(_MaxSizeLoadElementValue_);
filename = InFilename;
Initialise();
- fp=fopen(InFilename,"rb");
+ OpenFile(exception_on_error);
+ ParseHeader();
+ LoadElements();
+ CloseFile();
+}
+
+bool gdcmHeader::OpenFile(bool exception_on_error)
+ throw(gdcmFileError) {
+ fp=fopen(filename.c_str(),"rb");
if(exception_on_error) {
if(!fp)
throw gdcmFileError("gdcmHeader::gdcmHeader(const char *, bool)");
}
else
- dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", InFilename);
- ParseHeader();
- LoadElements();
+ dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", filename.c_str());
+ if ( fp )
+ return true;
+ return false;
}
+bool gdcmHeader::CloseFile(void) {
+ int closed = fclose(fp);
+ fp = (FILE *)0;
+ if (! closed)
+ return false;
+ return true;
+}
gdcmHeader::~gdcmHeader (void) {
//FIXME obviously there is much to be done here !
- fclose(fp);
return;
}
dicom_vr = vr;
}
+// Fourth semantics:
+// CMD Command
+// META Meta Information
+// DIR Directory
+// ID
+// PAT Patient
+// ACQ Acquisition
+// REL Related
+// IMG Image
+// SDY Study
+// VIS Visit
+// WAV Waveform
+// PRC
+// DEV Device
+// NMI Nuclear Medicine
+// MED
+// BFS Basic Film Session
+// BFB Basic Film Box
+// BIB Basic Image Box
+// BAB
+// IOB
+// PJ
+// PRINTER
+// RT Radio Therapy
+// DVH
+// SSET
+// RES Results
+// CRV Curve
+// OLY Overlays
+// PXL Pixels
+//
+
/**
* \ingroup gdcmHeader
* \brief Discover what the swap code is (among little endian, big endian,
sw = 3412;
}
-void gdcmHeader::GetPixels(size_t lgrTotale, void* _Pixels) {
- size_t pixelsOffset;
- pixelsOffset = GetPixelOffset();
- fseek(fp, pixelsOffset, SEEK_SET);
- if (IsJPEGLossless()) {
- _Pixels=_IdDcmJpegRead(fp);
- } else {
- fread(_Pixels, 1, lgrTotale, fp);
- }
-}
-
-
-
/**
* \ingroup gdcmHeader
* \brief Find the value representation of the current tag.
// and the dictionary entry depending on them.
guint16 CorrectGroup = SwapShort(ElVal->GetGroup());
guint16 CorrectElem = SwapShort(ElVal->GetElement());
- gdcmDictEntry * NewTag = GetDictEntryByKey(CorrectGroup, CorrectElem);
+ gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
+ CorrectElem);
if (!NewTag) {
// This correct tag is not in the dictionary. Create a new one.
NewTag = new gdcmDictEntry(CorrectGroup, CorrectElem);
return;
}
- // FIXME The exact size should be length if we move to strings or whatever
+ // We need an additional byte for storing \0 that is not on disk
char* NewValue = (char*)malloc(length+1);
if( !NewValue) {
dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue");
return g;
}
-
-
-
-//
-// TODO : JPR Pour des raisons d'homogeneité de noms,
-// remplacer les quelques GetxxxByKey
-// par des GetxxxByNumber, lorsqu'on passe gr, el en param.
-// il peut etre interessant de rajouter des GetxxxByKey, auxquels on passe *vraiment* une TagKey
-//
-
/**
* \ingroup gdcmHeader
* \brief Build a new Element Value from all the low level arguments.
* @param Group group of the underlying DictEntry
* @param Elem element of the underlying DictEntry
*/
-gdcmElValue* gdcmHeader::NewElValueByKey(guint16 Group, guint16 Elem) {
+gdcmElValue* gdcmHeader::NewElValueByNumber(guint16 Group, guint16 Elem) {
// Find out if the tag we encountered is in the dictionaries:
- gdcmDictEntry * NewTag = GetDictEntryByKey(Group, Elem);
+ gdcmDictEntry * NewTag = GetDictEntryByNumber(Group, Elem);
if (!NewTag)
NewTag = new gdcmDictEntry(Group, Elem);
gdcmElValue* NewElVal = new gdcmElValue(NewTag);
if (!NewElVal) {
- dbg.Verbose(1, "gdcmHeader::NewElValueByKey",
+ dbg.Verbose(1, "gdcmHeader::NewElValueByNumber",
"failed to allocate gdcmElValue");
return (gdcmElValue*)0;
}
*/
int gdcmHeader::ReplaceOrCreateByNumber(string Value, guint16 Group, guint16 Elem ) {
- gdcmElValue* nvElValue=NewElValueByKey(Group, Elem);
+ gdcmElValue* nvElValue=NewElValueByNumber(Group, Elem);
PubElValSet.Add(nvElValue);
PubElValSet.SetElValueByNumber(Value, Group, Elem);
return(1);
// has to be considered as finished.
return (gdcmElValue *)0;
- NewElVal = NewElValueByKey(g, n);
+ NewElVal = NewElValueByNumber(g, n);
FindVR(NewElVal);
FindLength(NewElVal);
if (errno == 1)
numPixel = 0x1010;
else
numPixel = 0x0010;
- gdcmElValue* PixelElement = PubElValSet.GetElementByNumber(grPixel, numPixel);
+ gdcmElValue* PixelElement = PubElValSet.GetElementByNumber(grPixel,
+ numPixel);
if (PixelElement)
return PixelElement->GetOffset();
else
* @param element element of the searched DictEntry
* @return Corresponding DictEntry when it exists, NULL otherwise.
*/
-gdcmDictEntry * gdcmHeader::GetDictEntryByKey(guint16 group, guint16 element) {
+gdcmDictEntry * gdcmHeader::GetDictEntryByNumber(guint16 group,
+ guint16 element) {
gdcmDictEntry * found = (gdcmDictEntry*)0;
if (!RefPubDict && !RefShaDict) {
dbg.Verbose(0, "gdcmHeader::GetDictEntry",
"we SHOULD have a default dictionary");
}
if (RefPubDict) {
- found = RefPubDict->GetTagByKey(group, element);
+ found = RefPubDict->GetTagByNumber(group, element);
if (found)
return found;
}
if (RefShaDict) {
- found = RefShaDict->GetTagByKey(group, element);
+ found = RefShaDict->GetTagByNumber(group, element);
if (found)
return found;
}
gdcmElValSet ShaElValSet;
/// Refering underlying filename.
string filename;
- FILE * fp;
// FIXME sw should be an enum e.g.
//enum EndianType {
gdcmElValue* NewManualElValToPubDict(string NewTagName, string VR);
void SetMaxSizeLoadElementValue(long);
- gdcmDictEntry * GetDictEntryByKey(guint16, guint16);
+ gdcmDictEntry * GetDictEntryByNumber(guint16, guint16);
gdcmDictEntry * GetDictEntryByName(string name);
// ElValue related utilities
gdcmElValue * ReadNextElement(void);
- gdcmElValue * NewElValueByKey(guint16 group, guint16 element);
+ gdcmElValue * NewElValueByNumber(guint16 group, guint16 element);
gdcmElValue * NewElValueByName(string name);
void FindLength(gdcmElValue *);
void FindVR(gdcmElValue *);
bool IsAnInteger(gdcmElValue *);
void LoadElements(void);
+protected:
+ FILE * fp;
+ FileType filetype;
+ bool OpenFile(bool exception_on_error = false)
+ throw(gdcmFileError);
+ bool CloseFile(void);
+ int write(ostream&);
+ int anonymize(ostream&); // FIXME : anonymize should be a friend ?
+public:
+ bool IsReadable(void);
bool IsImplicitVRLittleEndianTransferSyntax(void);
bool IsExplicitVRLittleEndianTransferSyntax(void);
bool IsDeflatedExplicitVRLittleEndianTransferSyntax(void);
bool IsJPEGExtendedProcess2_4TransferSyntax(void);
bool IsJPEGExtendedProcess3_5TransferSyntax(void);
bool IsJPEGSpectralSelectionProcess6_8TransferSyntax(void);
-
bool IsJPEGLossless(void);
bool IsDicomV3(void);
-protected:
- FileType filetype;
- int write(ostream&);
- int anonymize(ostream&); // FIXME : anonymize should be a friend ?
-public:
- bool IsReadable(void);
virtual void ParseHeader(bool exception_on_error = false)
throw(gdcmFormatError);
- gdcmHeader(const char *filename, bool exception_on_error = false)
- throw(gdcmFileError);
+ gdcmHeader(const char *filename, bool exception_on_error = false);
virtual ~gdcmHeader();
size_t GetPixelOffset(void);
- void GetPixels(size_t, void *);
int GetSwapCode(void) { return sw; }
// TODO Swig int SetPubDict(string filename);